Nếu tích cực, tổng hợp tất cả các mục. Nếu âm, trả lại từng cái


28

Tôi cần tìm cách cho SUM()tất cả các giá trị dương cho numvà trả SUM()về tất cả các số dương và một hàng riêng cho mỗi số âm. Dưới đây là một mẫu 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)

Và đây là đầu ra mong muốn của tôi (số dương cho mỗi lần bán hàng SUM()và tiêu cực nhận được một dòng riêng lẻ):

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

Câu trả lời:


26

Thử đi:

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

Nếu bạn muốn cả hai sumgiá trị trong một hàng thì bạn phải tạo hàm maxValue(và minValue) và sử dụng hàm này như sum(maxValue(0, num))sum(minValue(0, num)). Điều này được mô tả trong: Có hàm Max trong SQL Server có hai giá trị như Math.Max ​​trong .NET không?


8
Tôi đã sửa truy vấn. Cần UNION ALLlà tốt, không UNION.
ypercubeᵀᴹ

24

Điều này cũng hoạt động:

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

Giả định:

  • Id bắt đầu từ 1, do đó nó có thể sử dụng THEN 0. salesid ELSE salesid+id+1cũng sẽ làm việc
  • 0 được coi là số dương, do đó >= 0( Không có dương hay âm? ). Mặc dù x+0=xdường như làm cho =dấu hiệu không cần thiết, nhưng nó giúp nhớ rằng trường hợp này đã không bị lãng quên và cách xử lý 0 (dưới dạng SUM hoặc dưới dạng một hàng riêng lẻ). Nếu the SUM() of all positive numberscó nghĩa là SUM of strictly positive numbers(tức là> 0), thì =không cần thiết.

Nó phải được kiểm tra với dữ liệu thực và chỉ mục, nhưng chỉ với 1 lần quét bảng, hiệu suất có thể tốt hơn một chút trong một số trường hợp.

Sự vắng mặt của một chỉ mục dường như có tác động nhỏ hơn với truy vấn này trên dữ liệu thử nghiệm bên dưới:

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

Bạn có thể đơn giản hóa mệnh đề nhóm của mình bằng một iif như thế này: GROUP BY salesid, iif(num >= 0, 0, id) Truy vấn tuyệt vời.
2023861

1
Có nhưng OP sẽ phải cài đặt SQL Server đầu tiên 2012. IIF bắt đầu với SQL Server 2012: msdn.microsoft.com/en-us/l Library / hh213574.aspx . OP đã gắn thẻ câu hỏi của anh ấy với SQL Server 2008
Julien Vavasseur
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.