จะคูณแถวสำหรับคอลัมน์ที่มีค่าลบและศูนย์ได้อย่างไร


10

ฉันกำลังพยายามรับผลิตภัณฑ์ของทุกแถวสำหรับคอลัมน์ที่ระบุในการจัดกลุ่มตามแบบสอบถาม ตัวอย่างส่วนใหญ่ที่ฉันได้พบจุดที่ฉันมีต่อการรวมexp, sumและlog

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

ปัญหาที่ฉันมีอยู่คือคอลัมน์มีค่าศูนย์บางค่าและทำให้ฉันได้รับข้อผิดพลาดนี้เมื่อค่าศูนย์ส่งผ่านไปยังlogฟังก์ชัน:

การดำเนินการจุดลอยตัวไม่ถูกต้องเกิดขึ้น

ฉันคิดว่าฉันสามารถหลีกเลี่ยงปัญหานี้ได้ด้วยการใช้caseนิพจน์ แต่นั่นก็ไม่เป็นไปตามที่ฉันคิดว่ามันควรจะเป็นเพราะดูเหมือนว่าจะประเมินทุกกรณี

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

รับชุดผลลัพธ์ต่อไปนี้:

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

ฉันคาดว่าจะได้แถวต่อไปนี้:

Name  Product
_____________
a     2
b     0

ดังนั้นโดยสรุป ... คุณจะคูณแถวในคอลัมน์ที่สามารถมีตัวเลขค่าลบหรือศูนย์ได้อย่างไร

คำตอบ:


13

ความมหัศจรรย์ของNULLIFดูเหมือนจะเป็นการหลอกลวงสำหรับคำถามทดสอบในคำถามของคุณ เนื่องจากคุณใช้ตัวอย่างที่แตกต่างจากในซอฟแวร์ SQL Fiddle ของคุณฉันไม่รู้ว่านั่นคือสิ่งที่คุณต้องการหรือไม่

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;

ผลตอบแทน:

Name    Product
a       2
b       0

หากคุณต้องการโซลูชันทั่วไปที่จัดการกับจำนวนลบและตัวพิมพ์ขอบอื่น ๆ ให้ดูตัวอย่างProduct Aggregate ใน T-SQL กับ CLRโดย Scott Burkow หนึ่งการสร้าง T-SQL จากบทความนั้นคือ:

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)

สาเหตุที่CASEนิพจน์ดั้งเดิมของคุณใช้งานไม่ได้ตามที่คาดไว้จากเอกสารสำหรับCASE (Transact-SQL) (เน้นการเน้น):

คุณควรขึ้นอยู่กับคำสั่งของการประเมินผลของเงื่อนไขเมื่อนิพจน์สเกลาร์ (รวมทั้งที่ไม่ได้มีความสัมพันธ์ย่อยคำสั่งว่าการกลับมาเกลา) ไม่ได้สำหรับการแสดงออกรวม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.