Jika positif, jumlahkan semua item. Jika negatif, kembalikan masing-masing

28

Saya perlu menemukan cara untuk SUM()semua nilai positif untuk numdan mengembalikan SUM()semua angka positif dan satu baris individual untuk setiap angka negatif. Di bawah ini adalah contoh 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)

Dan ini adalah output yang saya inginkan (angka positif untuk setiap salesid SUM()dan negatif mendapatkan garis individual kembali):

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

Jawaban:

26

Coba ini:

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

Jika Anda ingin kedua sumnilai dalam satu baris maka Anda harus membuat fungsi maxValue(dan minValue) dan menggunakan ini sebagai sum(maxValue(0, num))dan sum(minValue(0, num)). Ini dijelaskan dalam: Apakah ada fungsi Max di SQL Server yang mengambil dua nilai seperti Math.Max ​​di .NET?

Marco
sumber
8
Saya memperbaiki kueri. Dibutuhkan UNION ALLjuga, tidak UNION.
ypercubeᵀᴹ
24

Ini juga berfungsi:

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

Asumsi:

  • Id dimulai pada 1, maka itu bisa digunakan THEN 0. salesid ELSE salesid+id+1akan bekerja juga
  • 0 dianggap bilangan positif, maka >= 0( Apakah nol positif atau negatif? ). Meskipun x+0=xtampaknya membuat =tanda itu tidak perlu, ada baiknya diingat bahwa kasus ini belum dilupakan dan bagaimana 0 ditangani (sebagai SUM atau sebagai baris individual). Jika the SUM() of all positive numbersberarti SUM of strictly positive numbers(yaitu> 0), maka =tidak diperlukan.

Ini harus diuji dengan data dan indeks nyata, tetapi dengan hanya 1 tabel scan, kinerja mungkin sedikit lebih baik dalam beberapa kasus.

Tidak adanya indeks tampaknya memiliki dampak yang lebih kecil dengan kueri ini pada data uji di bawah:

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
sumber
Anda dapat menyederhanakan klausa grup Anda dengan iif seperti ini: GROUP BY salesid, iif(num >= 0, 0, id) Cool query.
user2023861
1
Ya tapi OP harus menginstal SQL Server 2012. IIF dimulai dengan SQL Server 2012: msdn.microsoft.com/en-us/library/hh213574.aspx . OP telah menandai pertanyaannya dengan SQL Server 2008.
Julien Vavasseur