Bagaimana mengalikan baris untuk kolom yang berisi nilai negatif dan nol?


10

Saya mencoba untuk mendapatkan Produk dari semua baris untuk kolom tertentu dalam grup berdasarkan permintaan. Kebanyakan contoh yang saya temukan menunjukkan saya ke arah penggabungan exp, sumdanlog

exp(sum(log([Column A])))

Masalah yang saya alami adalah bahwa kolom berisi beberapa angka nol untuk nilai dan dengan demikian saya mendapatkan kesalahan ini ketika angka nol diteruskan ke logfungsi:

Terjadi operasi floating point yang tidak valid.

Saya pikir saya bisa mengatasi ini dengan menggunakan caseekspresi, tapi itu tidak berfungsi seperti yang saya pikir seharusnya, karena sepertinya mengevaluasi semua kasus ...

select 
  Name,
  Product = case 
    when min([Value]) = 0 then 0 
    when min([Value]) <> 0 then exp(sum(log(I))) -- trying to get the product of all rows in this column
  end
 from ids
 group by Name

SqlFiddle

Diberikan set hasil berikut:

Id  Name  Value
_________________________________
1   a     1
2   a     2
3   b     0
4   b     1

Saya berharap mendapatkan baris berikut:

Name  Product
_____________
a     2
b     0

Jadi dalam ringkasan ... Bagaimana Anda mengalikan baris dalam kolom yang dapat berisi angka bernilai negatif atau nol?

Jawaban:


13

Keajaiban NULLIF tampaknya melakukan trik untuk kasus uji dalam pertanyaan Anda. Karena Anda menggunakan contoh berbeda dari pada SQL Fiddle Anda, saya tidak tahu apakah itu yang Anda inginkan juga.

CREATE TABLE dbo.Ids
(
    Id INT NOT NULL IDENTITY(1, 1),
    Value INT,
    Name NVARCHAR(3)
);
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'a', 1 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'a', 2 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'b', 0 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'b', 1 );

SELECT   Name,
         CASE WHEN MIN(Value) = 0 THEN 0
              WHEN MIN(Value) > 0 THEN EXP(SUM(LOG(NULLIF(Value, 0)))) -- trying to get the product of all rows in this column
         END AS Product
FROM     Ids
GROUP BY Name;

Pengembalian:

Name    Product
a       2
b       0

Jika Anda memerlukan solusi yang lebih umum yang menangani angka negatif dan kasus tepi lainnya, lihat misalnya Agregat Produk dalam T-SQL versus CLR oleh Scott Burkow. Satu konstruksi T-SQL dari artikel itu adalah:

EXP(SUM(LOG(NULLIF(ABS([Value]), 0))))
*
IIF(SUM(IIF([Value] = 0, 1, NULL)) > 0, 0, 1)
*
IIF(SUM(IIF([Value] < 0, 1, 0)) % 2 = 1, -1, 1)

Mengapa CASEekspresi asli Anda tidak berfungsi seperti yang diharapkan, dari dokumentasi untuk CASE (Transact-SQL) (penekanan ditambahkan):

Anda hanya harus bergantung pada urutan evaluasi kondisi KETIKA untuk ekspresi skalar (termasuk sub-kueri yang tidak berkorelasi yang mengembalikan skalar), bukan untuk ekspresi agregat .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.