Si es positivo, suma todos los artículos. Si es negativo, devuelva cada uno

28

Necesito encontrar una forma de obtener SUM()todos los valores positivos numy devolver SUM()todos los números positivos y una fila individual para cada número negativo. A continuación se muestra una muestra 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)

Y esta es mi salida deseada (los números positivos para cada salesid SUM()y los negativos obtienen una línea individual devuelta):

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

Respuestas:

26

Prueba esto:

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 desea ambos sumvalores en una fila, debe crear una función maxValue(y minValue) y usarla como sum(maxValue(0, num))y sum(minValue(0, num)). Esto se describe en: ¿Existe una función Max en SQL Server que tome dos valores como Math.Max ​​en .NET?

Marco
fuente
8
Arregle la consulta. Necesario UNION ALLtambién, no UNION.
ypercubeᵀᴹ
24

Esto también funciona:

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

Suposiciones

  • Id comienza en 1, por lo tanto, puede usar THEN 0. salesid ELSE salesid+id+1funcionaría tan bien
  • 0 se considera un número positivo, de ahí el >= 0( ¿Es cero positivo o negativo? ). Aunque x+0=xparece que el =signo es innecesario, ayuda a recordar que este caso no se ha olvidado y cómo se maneja 0 (como SUM o como fila individual). Si the SUM() of all positive numberssignifica SUM of strictly positive numbers(es decir,> 0), entonces =no es necesario.

Debe probarse con datos e índices reales, pero con solo 1 escaneo de tabla, el rendimiento puede ser un poco mejor en algunos casos.

La ausencia de un índice parece tener un impacto menor con esta consulta en los datos de prueba a continuación:

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
fuente
Puede simplificar su cláusula de grupo con un iif como este: GROUP BY salesid, iif(num >= 0, 0, id) consulta genial.
user2023861
1
Sí, pero OP tendría que instalar primero SQL Server 2012. IIF comienza con SQL Server 2012: msdn.microsoft.com/en-us/library/hh213574.aspx . OP ha etiquetado su pregunta con SQL Server 2008.
Julien Vavasseur