Se positivo, sommare tutti gli elementi. Se negativo, restituisci ognuno


28

Ho bisogno di trovare un modo per SUM()tutti i valori positivi per nume restituire il numero SUM()di tutti i numeri positivi e una singola riga per ciascun numero negativo. Di seguito è riportato un esempio 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)

E questo è il risultato desiderato (i numeri positivi per ciascun salesid SUM()e i negativi restituiscono una singola riga):

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

Risposte:


26

Prova questo:

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

Se si desidera entrambi i sumvalori in una riga, è necessario creare una funzione maxValue(e minValue) e utilizzarla come sum(maxValue(0, num))e sum(minValue(0, num)). Questo è descritto in: Esiste una funzione Max in SQL Server che accetta due valori come Math.Max ​​in .NET?


8
Ho corretto la query. Necessario UNION ALL, no UNION.
ypercubeᵀᴹ

24

Funziona anche questo:

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

ipotesi:

  • L'id inizia da 1, quindi può usare THEN 0. salesid ELSE salesid+id+1funzionerebbe pure
  • 0 è considerato un numero positivo, quindi il >= 0( è zero positivo o negativo? ). Anche se x+0=xsembra rendere =superfluo il segno, aiuta a ricordare che questo caso non è stato dimenticato e come viene gestito lo 0 (come SOMMA o come singola riga). Se the SUM() of all positive numberssignifica SUM of strictly positive numbers(cioè> 0), allora =non è necessario.

Deve essere testato con dati e indici reali, ma con una sola scansione di tabella, in alcuni casi le prestazioni potrebbero essere leggermente migliori.

L'assenza di un indice sembra avere un impatto minore con questa query sui dati di test di seguito:

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

Puoi semplificare la tua clausola di gruppo con un iif come questo: GROUP BY salesid, iif(num >= 0, 0, id) Cool query.
user2023861

1
Sì, ma OP dovrebbe prima installare SQL Server 2012. IIF inizia con SQL Server 2012: msdn.microsoft.com/en-us/library/hh213574.aspx . OP ha taggato la sua domanda con SQL Server 2008.
Julien Vavasseur,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.