2017-06-15 49 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