web-dev-qa-db-fra.com

Si positif, additionnez tous les éléments. Si négatif, retournez chacun

J'ai besoin de trouver un moyen de SUM() toutes les valeurs positives pour num et de retourner la SUM() de tous les nombres positifs et une ligne individuelle pour chaque nombre négatif. Voici un exemple de 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)

Et voici ma sortie souhaitée (les nombres positifs pour chaque salesid SUM() et les négatifs obtiennent une ligne individuelle retournée):

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

Essaye ça:

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

Si vous voulez à la fois les valeurs sum sur une même ligne, vous devez créer une fonction maxValue (et minValue) et l'utiliser comme sum(maxValue(0, num)) et sum(minValue(0, num)). Ceci est décrit dans: Existe-t-il une fonction Max dans SQL Server qui prend deux valeurs comme Math.Max ​​dans .NET?

25
Marco

Cela fonctionne aussi:

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

Hypothèses:

  • L'ID commence à 1, il peut donc utiliser THEN 0. salesid ELSE salesid+id+1 Fonctionnerait également
  • 0 est considéré comme un nombre positif, d'où le >= 0 ( zéro est-il positif ou négatif? ). Bien que x+0=x Semble rendre le signe = Inutile, il permet de se rappeler que ce cas n'a pas été oublié et comment 0 est traité (en tant que SUM ou en tant que ligne individuelle). Si the SUM() of all positive numbers signifie SUM of strictly positive numbers (C'est-à-dire> 0), alors = N'est pas nécessaire.

Il doit être testé avec des données et des index réels, mais avec un seul scan de table, les performances peuvent être un peu meilleures dans certains cas.

L'absence d'index semble avoir un impact moindre avec cette requête sur les données de test ci-dessous:

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
Julien Vavasseur