2017-06-15 16 views
1

我工作的公司转售数据,因此可能出售两次相同的“单位”。我正在尝试做盈利能力计算,但由于如何设置表,所以会遇到麻烦。SQL Server - 处理一个奇怪的表关系

基本上我们有两个表,我们称之为数据和销售。

数据:

dataid cost 
1  $1.00 
2  $2.00 

售:

saleid dataid price 
1  1  $5.00 
2  2  $3.00 
3  2  $4.00 

我需要做的是加入表中,使得成本仅算的上了第一笔生意。就像这样:

利润:

saleid dataid price cost profit 
1  1  $5.00 $1.00 $4.00 
2  2  $3.00 $2.00 $1.00 
3  2  $4.00 $0.00 $4.00 

我工作近十亿行所以性能是一个问题为好。我意识到表结构非常愚蠢,但重构数据库不是一种选择。有什么建议么?

+0

你是什么意思, “第一”?在升序saleid? SQL表没有顺序。您是否对有序SQL结果集(查询结果)进行了说明?它的排序来源是什么? – philipxy

回答

0

这似乎很奇怪。您可以使用row_number()做到这一点:

select s.*, coalesce(c.cost, 0) as cost, 
     (s.price - coalesce(c.cost, 0)) as profit 
from (select s.*, 
      row_number() over (partition by s.dataid order by s.saleid) as seqnum 
     from sales s 
    ) s left join join 
    cost c 
    on c.dataid = s.dataid; 

我要指出,你想在sales(dataid, saleid)性能的指标。

1

或者您可以尝试使用row_number(),正如Gordon Linoff从之前的答案中所建议的那样确定第一次销售。

数据:使用CTE和ROW_NUMBER

IF (OBJECT_ID('tempdb..#TmpData') IS NOT NULL) 
     BEGIN 
      DROP TABLE #TmpData 
     END 

    CREATE TABLE #TmpData (dataid INT, cost MONEY,) 
    CREATE CLUSTERED INDEX IX_TmpData_dataid ON #TmpData (dataid) 

    INSERT INTO #TmpData 
      (dataid, cost) 
    VALUES (1, 1), 
      (2, 2) 

    IF (OBJECT_ID('tempdb..#TmpSale') IS NOT NULL) 
     BEGIN 
      DROP TABLE #TmpSale 
     END 

    CREATE TABLE #TmpSale 
     (
      saleid INT , 
      dataid INT , 
      price MONEY 
     ) 
    CREATE CLUSTERED INDEX IX_TmpSale ON #TmpSale (saleid) 
    CREATE NONCLUSTERED INDEX IX_TmpSale_dataid ON #TmpSale (dataid) 


    INSERT INTO #TmpSale 
      (saleid, dataid, price) 
    VALUES (1, 1, 5), 
      (2, 2, 3), 
      (3, 2, 4) 

;WITH PROFIT 
       AS (SELECT d.dataid d_dataid , 
          d.cost , 
          s.saleid , 
          s.dataid s_dataid , 
          price , 
          ROW_NUMBER() OVER (PARTITION BY d.dataid ORDER BY s.saleid) ctr 
        FROM  #TmpData D 
          JOIN #TmpSale S ON S.dataid = D.dataid 
       ) 
     SELECT saleid , 
       d_dataid dataid , 
       price , 
       IIF(ctr = 1, cost, 0) cost , 
       IIF(ctr = 1, (price - cost), price) profit 
     FROM PROFIT 
     OPTION (MAXRECURSION 32767) 

结果:

saleid  dataid  price cost profit 
    ----------- ----------- ------- ------- -------- 
    1   1   5.00 1.00 4.00 
    2   2   3.00 2.00 1.00 
    3   2   4.00 0.00 4.00 
0

这里要注意这个问题是不是就指数或性能。 因为你已经抛出了样本表结构。

恕我直言,正确的索引会,

CREATE CLUSTERED INDEX IX_TmpData_dataid ON #TmpData (dataid) 

CREATE CLUSTERED INDEX IX_TmpSale ON #TmpSale (saleid) 
CREATE NONCLUSTERED INDEX IX_TmpSale_dataid ON #TmpSale (dataid)INCLUDE(profit) 

试试这个,

select saleid, dataid,t4.price,(case when rn=1 then cost else 0 end)Cost 
,price-(case when rn=1 then cost else 0 end)Profit 
FROM(
select a.saleid,a.dataid,a.price, d.cost 
,ROW_NUMBER()over(PARTITION by d.dataid order by d.dataid)rn 
    from #TmpSale a 
left join #TmpData d on a.dataid=d.dataid 
)t4