web-dev-qa-db-ja.com

正の場合、すべての項目を合計します。負の場合、それぞれを返します

numのすべての正の値をSUM()にして、すべての正の数のSUM()と、各負の数の個別の行を返す方法を見つける必要があります。以下はサンプルDDLです。

_Create Table #Be
(
    id int
    , salesid int
    , num decimal(16,4)
)

Insert Into #BE Values
    (1, 1, 12.32), (2, 1, -13.00), (3, 1, 14.00)
    , (4, 2, 12.12), (5, 2, 14.00), (6, 2, 21.23)
    , (7, 3, -12.32), (8,3, -43.23), (9, 3, -2.32)
_

そして、これは私の望ましい出力です(各salesidの正の数SUM()と負の数は、個別の行を返します):

_salesid    num
1          26.32
1          -13.00
2          47.35
3          -12.32
3          -43.23
3          -2.32
_
27
user2676140

これを試して:

_SELECT   salesid, sum(num) as num
FROM     #BE
WHERE    num > 0
GROUP BY salesid
UNION ALL
SELECT   salesid, num
FROM     #BE
WHERE    num < 0;
_

1つの行に両方のsum値が必要な場合は、maxValue(およびminValue)関数を作成し、これをsum(maxValue(0, num))およびsum(minValue(0, num))。これは以下で説明されています SQL Serverには、.NETのMath.Maxのような2つの値をとるMax関数がありますか?

25
Marco

これも機能します:

_SELECT salesid, SUM(num)
FROM #BE
GROUP BY salesid, CASE WHEN num >= 0 THEN 0 ELSE id END;
_

仮定:

  • IDは1から始まるため、_THEN 0_を使用できます。 _salesid ELSE salesid+id+1_も機能します
  • 0は正の数と見なされるため、_>= 0_( ゼロは正か負か )。 _x+0=x_は_=_記号を不要にするように見えますが、このケースは忘れられておらず、0が(SUMまたは個々の行として)処理される方法を覚えているのに役立ちます。 the SUM() of all positive numbersが_SUM of strictly positive numbers_を意味する場合(つまり、> 0)、_=_は必要ありません。

実際のデータとインデックスでテストする必要がありますが、テーブルスキャンが1つだけの場合、パフォーマンスが少し向上する場合があります。

インデックスがないことは、以下のテストデータに対するこのクエリの影響が小さいようです。

_SET NO COUNT ON
Create Table #Be(
  id int identity(0,1)
  ,salesid int,num decimal(16,4)
)
INSERT INTO #BE(salesid, num) 
SELECT CAST(Rand()*10 as int), Rand() - Rand()
GO 10000 -- or 100.000
_
23