Wenn positiv, summiere alle Punkte. Wenn negativ, geben Sie jeden zurück

28

Ich brauche den einen Weg zu finden , SUM()für alle positiven Werte numund die Rückkehr SUM()aller positiven Zahlen und einer einzelnen Zeile für jede negative Zahl. Unten finden Sie eine Beispiel-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 Verkäuferin SUM()und negative erhalten eine individuelle Zeile zurück):

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

Antworten:

26

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 sumWerte in einer Zeile haben möchten , müssen Sie eine maxValue(und minValue) Funktion erstellen und diese als sum(maxValue(0, num))und verwenden sum(minValue(0, num)). Dies ist beschrieben in: Gibt es eine Max-Funktion in SQL Server, die zwei Werte wie Math.Max ​​in .NET annimmt?

Marco
quelle
8
Ich habe die Abfrage behoben. Wird UNION ALLauch gebraucht , nicht UNION.
ypercubeᵀᴹ
24

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 es verwendet werden THEN 0. salesid ELSE salesid+id+1würde auch funktionieren
  • 0 gilt als positive Zahl, daher die >= 0( Ist Null positiv oder negativ? ). Obwohl x+0=xdas =Zeichen unnötig zu sein scheint , hilft es, sich daran zu erinnern, dass dieser Fall nicht vergessen wurde und wie mit 0 umgegangen wird (als SUMME oder als einzelne Zeile). Wenn the SUM() of all positive numbersbedeutet SUM of strictly positive numbers(dh> 0), dann =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 wirkt sich bei dieser Abfrage weniger auf die folgenden Testdaten aus:

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
Julien Vavasseur
quelle
Sie können Ihre Gruppenklausel mit einem iif wie folgt vereinfachen: GROUP BY salesid, iif(num >= 0, 0, id) Coole Abfrage.
user2023861
1
Ja, aber OP muss zuerst SQL Server 2012 installieren. IIF startet mit SQL Server 2012: msdn.microsoft.com/en-us/library/hh213574.aspx . OP hat seine Frage mit SQL Server 2008 getaggt.
Julien Vavasseur