เป็นไปได้หรือไม่ที่จะระบุเงื่อนไขใน Count ()?


391

เป็นไปได้Count()หรือไม่ที่จะระบุเงื่อนไข ฉันต้องการนับเฉพาะแถวที่มีเช่น "ผู้จัดการ" ในคอลัมน์ตำแหน่ง

ฉันต้องการที่จะทำมันในคำสั่งการนับไม่ได้ใช้WHERE; ฉันขอเกี่ยวกับเรื่องนี้เพราะผมต้องการที่จะนับทั้งผู้จัดการและอื่น ๆ ในเดียวกันSELECT(สิ่งที่ต้องการCount(Position = Manager), Count(Position = Other))เพื่อWHEREการใช้งานสำหรับฉันในตัวอย่างนี้ไม่มี


4
Boo สำหรับผู้ใช้ * ทั้งหมดให้ใช้ Count (SomeColumnInYourTable) โดยที่ Position = 'Manager'
Mark Dickinson

6
@ Mark: ในฐานข้อมูลที่ทันสมัยทั้งหมดนี้ไม่ได้สร้างความแตกต่างเลย
Philippe Leybaert

4
@ Mark & ​​Philippe: จริงๆแล้วมันสามารถสร้างความแตกต่างได้ หากเขตข้อมูลนั้นเป็นโมฆะและไม่ได้จัดทำดัชนีแบบสอบถามจำเป็นต้องสัมผัสทุกระเบียนในตารางดังนั้นการใช้ count (*) และ count (field) สามารถให้ผลลัพธ์ differnet และประสิทธิภาพที่แตกต่างกัน
Guffa

3
ฉันได้วิเคราะห์แผนการดำเนินการสำหรับ count (*) vs count (x) เป็นเวลาหลายปีและจนถึงตอนนี้ฉันยังไม่พบตัวเดียวที่แสดงความแตกต่างของประสิทธิภาพ นั่นเป็นเหตุผลที่ฉันต้องการเห็นตัวอย่างของแบบสอบถามที่มีความแตกต่าง
Philippe Leybaert

2
@ Matthew: เราไม่ได้พูดถึงSELECT *แต่SELECT COUNT(*)เป็นสัตว์ที่แตกต่างกันโดยสิ้นเชิง
Philippe Leybaert

คำตอบ:


663

หากคุณไม่สามารถ จำกัด คิวรีของตัวเองด้วยwhereประโยคคุณสามารถใช้ข้อเท็จจริงที่ว่าผลcountรวมนั้นจะนับเฉพาะค่าที่ไม่เป็นโมฆะเท่านั้น:

select count(case Position when 'Manager' then 1 else null end)
from ...

คุณยังสามารถใช้การsumรวมในวิธีที่คล้ายกัน:

select sum(case Position when 'Manager' then 1 else 0 end)
from ...

จะทำอย่างไรถ้าเขตข้อมูลของฉันเป็นจำนวนเต็มและฉันต้องการจับคู่ค่าว่าง มันใช้งานไม่ได้ด้วยวิธีนี้เลือกจำนวน (กรณี IntegerField เมื่อ 'NULL' จากนั้นเป็นโมฆะอีก 1 อัน) จาก
Faizan

2
@Faizan nullเป็นพิเศษ ใช้case when IntegerField is null then ...
Peet Brits

เมื่อทำงานกับเขตข้อมูลบูลีนคุณสามารถใช้สิ่งนี้:SUM(CONVERT(int, IsManager))
Simon_Weaver

2
SQL Server หมายถึงคำสั่งelse nullfor caseดังนั้นcount()ตัวอย่างอาจสั้นกว่า 10 อักขระ (ถ้าคุณนับจำนวนช่องว่าง)
ไมเคิล - Clay Shirky อยู่ที่ไหน

212

สมมติว่าคุณไม่ต้องการ จำกัด แถวที่ส่งคืนเนื่องจากคุณรวมค่าอื่นด้วยเช่นกันคุณสามารถทำสิ่งนี้ได้:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount
from ...

สมมติว่าภายในคอลัมน์เดียวกับที่คุณมีค่าของผู้จัดการหัวหน้างานและหัวหน้าทีมคุณสามารถได้รับการนับของแต่ละอย่างเช่นนี้:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount,
    count(case when Position = 'Supervisor' then 1 else null end) as SupervisorCount,
    count(case when Position = 'Team Lead' then 1 else null end) as TeamLeadCount,
from ...

3
@RedFilter ก็ไม่ได้จำเป็นที่จะต้องระบุelseส่วนหนึ่งเพียงแค่มันขวาหลังจากที่end 1
เดนิส Valeev

7
@Denis: ถูกต้อง - ฉันมักจะปล่อยให้elseมันเป็นเอกสารที่ดีกว่าผลของคำสั่งกรณีโดยเฉพาะอย่างยิ่งสำหรับนักพัฒนา SQL ใหม่ สำหรับความกะทัดรัดมันสามารถลบออกได้ในกรณีนี้
RedFilter

30

คำตอบของ @Guffa นั้นยอดเยี่ยมเพียงแค่ชี้ให้เห็นว่าคำสั่ง IF อาจจะสะอาดกว่า

select count(IF(Position = 'Manager', 1, NULL)) as ManagerCount
from ...

21

ขึ้นอยู่กับสิ่งที่คุณหมายถึง แต่การตีความความหมายอื่น ๆ คือที่ที่คุณต้องการนับแถวด้วยค่าบางอย่าง แต่ไม่ต้องการ จำกัดSELECTเพียงแค่แถวเหล่านั้น ...

คุณจะใช้โดยใช้SUM()ประโยคเช่นนี้แทนการใช้COUNT(): เช่น

SELECT SUM(CASE WHEN Position = 'Manager' THEN 1 ELSE 0 END) AS ManagerCount,
    SUM(CASE WHEN Position = 'CEO' THEN 1 ELSE 0 END) AS CEOCount
FROM SomeTable

13

คุณสามารถใช้ Pivot Keyword ได้หากคุณใช้ SQL 2005 ขึ้นไป

ข้อมูลเพิ่มเติมและจากTechnet

SELECT *
FROM @Users
PIVOT (
    COUNT(Position)
    FOR Position
    IN (Manager, CEO, Employee)
) as p

ชุดข้อมูลทดสอบ

DECLARE @Users TABLE (Position VARCHAR(10))
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('CEO')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')

5

คุณหมายถึงแค่นี้:

SELECT Count(*) FROM YourTable WHERE Position = 'Manager'

ถ้าเป็นเช่นนั้น yup ที่ใช้งานได้!


1
การแก้ไขแสดงให้เห็นว่าเขาไม่ต้องการ จำกัด แถวด้วยคำสั่ง WHERE
KinSlayerUY

4

ฉันรู้ว่ามันเก่าจริง ๆ แต่ฉันNULLIFชอบกลอุบายสำหรับสถานการณ์ดังกล่าวและฉันไม่พบข้อเสีย เพียงแค่ดูตัวอย่างการคัดลอกและวางของฉันซึ่งไม่สามารถใช้งานได้จริง แต่สาธิตวิธีการใช้

NULLIF อาจส่งผลเสียต่อประสิทธิภาพการทำงานของคุณเล็กน้อย แต่ฉันคิดว่ามันน่าจะเร็วกว่าเคียวรีย่อย

DECLARE @tbl TABLE ( id [int] NOT NULL, field [varchar](50) NOT NULL)

INSERT INTO @tbl (id, field)
SELECT 1, 'Manager'
UNION SELECT 2, 'Manager'
UNION SELECT 3, 'Customer'
UNION SELECT 4, 'Boss'
UNION SELECT 5, 'Intern'
UNION SELECT 6, 'Customer'
UNION SELECT 7, 'Customer'
UNION SELECT 8, 'Wife'
UNION SELECT 9, 'Son'

SELECT * FROM @tbl

SELECT 
    COUNT(1) AS [total]
    ,COUNT(1) - COUNT(NULLIF([field], 'Manager')) AS [Managers]
    ,COUNT(NULLIF([field], 'Manager')) AS [NotManagers]
    ,(COUNT(1) - COUNT(NULLIF([field], 'Wife'))) + (COUNT(1) - COUNT(NULLIF([field], 'Son'))) AS [Family]
FROM @tbl

ความเห็นชื่นชม :-)



2

ฉันคิดว่าคุณสามารถใช้ WHERE clause เพื่อเลือกเฉพาะการนับจำนวนเรคคอร์ด


ทำไมฉันถึงลงคะแนนเสียงได้? หลังจากที่ฉันตอบ (หรืออาจเป็นเวลาเดียวกัน) หลายคนตอบสิ่งที่คล้ายกันและพวกเขาไม่ได้รับการโหวตใด ๆ / :(
NawaMan

4
คุณจะได้รับ downvote เพราะคำถามคือ "ระบุเงื่อนไขในการนับ" ไม่ "นับค่าตามเงื่อนไข" ดังนั้นคุณกำลังตอบคำถามผิด
Radon8472

3
มันไม่ยุติธรรมเลยที่จะ downvote คำตอบเมื่อเขียนคำตอบมันเป็นคำตอบที่ถูกต้องสำหรับคำถาม .... เขาเพิ่มข้อความพิเศษ 4 นาทีหลังจากคำตอบนี้!
ปีเตอร์

2

นี่คือสิ่งที่ฉันทำเพื่อรับชุดข้อมูลที่รวมทั้งจำนวนทั้งหมดและจำนวนที่ตรงตามเกณฑ์ภายในแต่ละคอนเทนเนอร์การจัดส่ง ขอให้ฉันตอบคำถาม "มีตู้สินค้าจัดส่งกี่รายการที่มีมากกว่า X% จำนวนมากกว่า 51 รายการ"

select
   Schedule,
   PackageNum,
   COUNT (UniqueID) as Total,
   SUM (
   case
      when
         Size > 51 
      then
         1 
      else
         0 
   end
) as NumOverSize 
from
   Inventory 
where
   customer like '%PEPSI%' 
group by
   Schedule, PackageNum


-4

เมื่อใช้สิ่งนี้คุณจะได้รับการนับสำหรับผู้จัดการ

Select Position, count(*) as 'Position Counter'
from your_table 
group by Position 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.