it-swarm.com.de

Wenn positiv, summieren Sie alle Elemente. Wenn negativ, geben Sie jeden zurück

Ich muss einen Weg finden, um SUM() alle positiven Werte für num und SUM() aller positiven Zahlen und eine einzelne Zeile für jede negative Zahl zurückzugeben. Unten finden Sie ein Beispiel für eine 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)

Und dies ist meine gewünschte Ausgabe (positive Zahlen für jede salesid SUM() und negative Zahlen erhalten eine einzelne Zeile zurückgegeben):

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

Versuche dies:

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

Wenn Sie beide sum -Werte in einer Zeile haben möchten, müssen Sie eine maxValue (und minValue) -Funktion erstellen und diese als sum(maxValue(0, num)) und sum(minValue(0, num)). Dies wird beschrieben in: Gibt es in SQL Server eine Max-Funktion, die zwei Werte wie Math.Max ​​in .NET annimmt?

25
Marco

Das funktioniert auch:

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

Annahmen:

  • ID beginnt bei 1, daher kann THEN 0 Verwendet werden. salesid ELSE salesid+id+1 Würde auch funktionieren
  • 0 wird als positive Zahl betrachtet, daher >= 0 ( Ist Null positiv oder negativ? ). Obwohl x+0=x Das = - Zeichen unnötig zu machen scheint, hilft es, sich daran zu erinnern, dass dieser Fall nicht vergessen wurde und wie 0 behandelt wird (als SUMME oder als einzelne Zeile). Wenn the SUM() of all positive numbersSUM of strictly positive numbers (D. H.> 0) bedeutet, wird = Nicht benötigt.

Es muss mit realen Daten und Indizes getestet werden, aber mit nur einem Tabellenscan kann die Leistung in einigen Fällen etwas besser sein.

Das Fehlen eines Index scheint bei dieser Abfrage einen geringeren Einfluss auf die folgenden Testdaten zu haben:

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