2017-06-15 8 views
1

私が働く会社はデータを転売しているので、同じ「ユニット」を2回販売することは可能です。私は収益性の計算をしようとしているが、テーブルがどのように設定されているかによって頭痛に冒されている。SQL Server - 奇妙なテーブル関係を扱う

基本的に2つのテーブルがあり、データとセールと呼ぶことにします。

データ:

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

、これを試してみてください?昇順では? 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

または、これを試すことができます。これは、先ほどの答えからGordon Linoffが提案した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) 

CTEとROW_NUMBERを使用して:

;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 
関連する問題