Если положительный, суммируйте все пункты. Если отрицательный, вернуть каждый

28

Мне нужно найти путь ко SUM()всем положительным значениям numи вернуть SUM()все положительные числа и отдельную строку для каждого отрицательного числа. Ниже приведен пример 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)

И это мой желаемый результат (положительные числа для каждого salesid SUM()и отрицательные значения возвращают отдельную строку):

salesid    num
1          26.32
1          -13.00
2          47.35
3          -12.32
3          -43.23
3          -2.32
user2676140
источник

Ответы:

26

Попробуй это:

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

Если вам нужны оба sumзначения в одной строке, вы должны создать функцию maxValueminValue) и использовать ее как sum(maxValue(0, num))и sum(minValue(0, num)). Это описано в: Есть ли в SQL Server функция Max, которая принимает два значения, такие как Math.Max ​​в .NET?

Marco
источник
8
Я исправил запрос. Нужно, UNION ALLа не UNION.
ypercubeᵀᴹ
24

Это тоже работает:

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

Предположения:

  • Идентификатор начинается с 1, следовательно, он может использовать THEN 0. salesid ELSE salesid+id+1будет работать так же
  • 0 считается положительным числом, следовательно >= 0( Ноль положительный или отрицательный? ). Хотя x+0=xкажется, что =знак делает ненужным, это помогает помнить, что этот случай не был забыт и как обрабатывается 0 (как SUM или как отдельная строка). Если the SUM() of all positive numbersозначает SUM of strictly positive numbers(то есть> 0), то =не нужно.

Он должен быть протестирован с реальными данными и индексами, но при сканировании только одной таблицы в некоторых случаях производительность может быть немного лучше.

Отсутствие индекса, по-видимому, оказывает меньшее влияние с этим запросом на тестовые данные ниже:

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
Жюльен Вавассер
источник
Вы можете упростить ваше групповое предложение с помощью iif, например: GROUP BY salesid, iif(num >= 0, 0, id) Классный запрос.
user2023861 30.06.16
1
Да, но OP должен сначала установить SQL Server 2012. IIF начинается с SQL Server 2012: msdn.microsoft.com/en-us/library/hh213574.aspx . ОП отметил свой вопрос с помощью SQL Server 2008.
Жюльен Вавассер