Sql Server ที่เทียบเท่ากับฟังก์ชันการรวม COUNTIF


164

ฉันกำลังสร้างแบบสอบถามด้วยGROUP BYประโยคที่ต้องการความสามารถในการนับระเบียนตามเงื่อนไขบางอย่างเท่านั้น (เช่นนับเฉพาะระเบียนที่ค่าคอลัมน์ที่แน่นอนเท่ากับ 1)

SELECT  UID, 
        COUNT(UID) AS TotalRecords, 
        SUM(ContractDollars) AS ContractDollars,
        (COUNTIF(MyColumn, 1) / COUNT(UID) * 100) -- Get the average of all records that are 1
FROM    dbo.AD_CurrentView
GROUP BY UID
HAVING  SUM(ContractDollars) >= 500000

COUNTIF()บรรทัดเห็นได้ชัดว่าล้มเหลวตั้งแต่ยังไม่มีฟังก์ชั่น SQL พื้นเมืองเรียกว่าCOUNTIFแต่ความคิดที่นี่คือการกำหนดอัตราร้อยละของทุกแถวที่มีค่า '1' สำหรับ MyColumn

มีความคิดเห็นเกี่ยวกับวิธีการนำไปใช้อย่างเหมาะสมในสภาพแวดล้อม MS SQL 2005 หรือไม่

คำตอบ:


339

คุณสามารถใช้SUM(ไม่COUNT!) รวมกับCASEคำสั่งเช่นนี้:

SELECT SUM(CASE WHEN myColumn=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView

หมายเหตุ: ในการทดสอบของฉันเองNULLนั้นไม่ได้มีปัญหาแม้ว่าจะขึ้นอยู่กับสภาพแวดล้อม คุณสามารถจัดการค่า null ได้เช่น:

SELECT SUM(CASE WHEN ISNULL(myColumn,0)=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView

3
(ฉันรู้ว่า OP ถามเกี่ยวกับ MS SQL แต่เป็นเพียงความคิดเห็นเล็กน้อยสำหรับผู้ใช้ SQLite ที่ทำสิ่งเดียวกัน) SQLite ไม่มีISNULLคุณสามารถทำแทนCASE WHEN myColumn IS NULLหรือใช้ifnull( stackoverflow.com/a/799406/1861346 )
Matt

54

ฉันมักจะทำในสิ่งที่ Josh แนะนำ แต่ได้ระดมสมองและทดสอบทางเลือกที่ไม่ค่อยชัดเจนซึ่งฉันรู้สึกอยากแบ่งปัน

คุณสามารถใช้ประโยชน์จากข้อเท็จจริงที่ว่า COUNT (ColumnName) ไม่นับ NULL และใช้สิ่งนี้:

SELECT COUNT(NULLIF(0, myColumn))
FROM AD_CurrentView

NULLIF - ส่งคืน NULL หากทั้งสองค่าที่ส่งผ่านเหมือนกัน

ข้อได้เปรียบ: แสดงเจตนาของคุณต่อแถว COUNT แทนที่จะแสดงสัญรูป SUM () ข้อเสีย: ไม่ชัดเจนว่ามันทำงานอย่างไร ("เวทมนต์" มักจะไม่ดี)


2
วิธีการแก้ปัญหานี้สามารถให้คำตอบที่แตกต่างกว่าผลรวมเมื่อกลุ่มมีเพียงโมฆะมันส่งผลให้ 1 แทน 0
KimvdLinde

โพสต์เก่า แต่ขอบคุณที่ช่วย ผมขยายมายากลและมีรอบ "เท่านั้น nulls" ปัญหาโดยการเพิ่มดังนี้ISNULL SELECT COUNT(NULLIF(0, ISNULL(myColumn, 0)))รอที่เพิ่งดูน่าเกลียด ...
pcdev

1
จะสมบูรณ์ถ้ามีฟังก์ชัน
NULLIFNOT

21

ฉันจะใช้ไวยากรณ์นี้ มันให้ผลเช่นเดียวกับคำแนะนำของ Josh และ Chris แต่ด้วยความได้เปรียบมันเป็น ANSI ที่น่าพอใจและไม่ผูกติดอยู่กับผู้ขายฐานข้อมูลรายใดรายหนึ่ง

select count(case when myColumn = 1 then 1 else null end)
from   AD_CurrentView

2
คำตอบของ Chris เป็นไปตาม Stndard SQL (คำแนะนำ: NULLIFรวมอยู่ในมาตรฐาน SQL-92) คำตอบของจอชสามารถเปลี่ยนได้อย่างง่ายดายในมาตรฐาน SQL โดยการแทนที่ด้วยisnull COALESCE
oneday เมื่อ

ฉันชอบคำตอบนี้ดีที่สุดเพราะได้แนวคิดว่า "การนับจำนวนแถว" ที่คริสแสดงอยู่ แต่สามารถขยายได้มากกว่าเนื่องจากคุณสามารถใช้ตัวดำเนินการเปรียบเทียบใด ๆ ได้ =ไม่ได้เป็นเพียง ฉันใช้มันเพื่อ "นับจำนวนการตอบกลับ> = 2"
Kristen Hammack

3

การเพิ่มคำตอบของ Josh

SELECT COUNT(CASE WHEN myColumn=1 THEN AD_CurrentView.PrimaryKeyColumn ELSE NULL END)
FROM AD_CurrentView

ทำงานได้ดีสำหรับฉัน (ใน SQL Server 2012) โดยไม่เปลี่ยน 'จำนวน' เป็น 'ผลรวม' และตรรกะเดียวกันนี้สามารถพกพาไปยัง 'มวลรวมที่มีเงื่อนไข' อื่นได้ เช่นการรวมตามเงื่อนไข:

SELECT SUM(CASE WHEN myColumn=1 THEN AD_CurrentView.NumberColumn ELSE 0 END)
FROM AD_CurrentView

2

เกี่ยวกับ

SELECT id, COUNT(IF status=42 THEN 1 ENDIF) AS cnt
FROM table
GROUP BY table

สั้นกว่าCASE:)

เพราะผลงานCOUNT()ไม่นับค่า null และIF/ CASEผลตอบแทน null ELSEเมื่อเงื่อนไขจะไม่ได้พบกันและไม่มี

SUM()ฉันคิดว่ามันเป็นดีกว่าการใช้


1

ไม่ใช่เฉพาะผลิตภัณฑ์ แต่มีมาตรฐาน SQL

SELECT COUNT() FILTER WHERE <condition-1>, COUNT() FILTER WHERE <condition-2>, ... FROM ...

เพื่อจุดประสงค์นี้. หรือบางสิ่งที่คล้ายกับมันมากฉันไม่รู้ว่าด้านบนของหมวก

และแน่นอนว่าผู้ขายจะชอบที่จะยึดติดกับโซลูชันที่เป็นกรรมสิทธิ์ของพวกเขา


1
ฉันไม่เคยได้ยินเรื่องนี้มาก่อนดังนั้นฉันจึงค้นหามัน ตามmodern-sql.com/feature/filter DBMS ที่สำคัญเท่านั้นที่จริง ๆ แล้วเสนอFILTERอนุประโยคคือ PostgreSQL แต่มันถูกจำลองโดยCASEทั้งหมด
Kristen Hammack

1

ทำไมไม่เป็นเช่นนี้

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1

1
เพราะเขาต้องการมากกว่าแค่การนับ เขาพยายามที่จะได้รับจำนวนแถวของกลุ่มแล้วรวมกลุ่มทั้งหมดซึ่งคุณไม่สามารถทำกับ WHERE ได้
Kristen Hammack

1

ฉันต้องใช้ COUNTIF () ในกรณีของฉันเป็นส่วนหนึ่งของคอลัมน์ SELECT ของฉันและเพื่อเลียนแบบ% ของจำนวนครั้งที่แต่ละรายการปรากฏในผลลัพธ์ของฉัน

ดังนั้นฉันใช้สิ่งนี้ ...

SELECT COL1, COL2, ... ETC
       (1 / SELECT a.vcount 
            FROM (SELECT vm2.visit_id, count(*) AS vcount 
                  FROM dbo.visitmanifests AS vm2 
                  WHERE vm2.inactive = 0 AND vm2.visit_id = vm.Visit_ID 
                  GROUP BY vm2.visit_id) AS a)) AS [No of Visits],
       COL xyz
FROM etc etc

แน่นอนคุณจะต้องจัดรูปแบบผลลัพธ์ตามข้อกำหนดการแสดงผลของคุณ


-2
SELECT COALESCE(IF(myColumn = 1,COUNT(DISTINCT NumberColumn),NULL),0) column1,
COALESCE(CASE WHEN myColumn = 1 THEN COUNT(DISTINCT NumberColumn) ELSE NULL END,0) AS column2
FROM AD_CurrentView
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.