วิธีรวมผลลัพธ์“ ศูนย์” /“ 0” ในการรวม COUNT รายการ


112

ฉันเพิ่งติดอยู่กับ SQL เล็กน้อย ฉันไม่คิดว่าฉันจะเรียบเรียงคำถามได้อย่างยอดเยี่ยมดังนั้นให้ฉันแสดงให้คุณเห็น

ฉันมีโต๊ะสองโต๊ะคนหนึ่งเรียกว่านัด ฉันกำลังพยายามส่งคืนจำนวนการนัดหมายที่บุคคลหนึ่งมีอยู่ (รวมถึงถ้าพวกเขามีศูนย์) การนัดหมายประกอบด้วยperson_idและมีการperson_idนัดหมายต่อครั้ง ดังนั้นจึงCOUNT(person_id)เป็นแนวทางที่สมเหตุสมผล

คำถาม:

SELECT person_id, COUNT(person_id) AS "number_of_appointments" 
FROM appointment 
GROUP BY person_id;

จะกลับมาถูกต้องจำนวนการนัดหมายที่ person_id มี อย่างไรก็ตามบุคคลที่มีการนัดหมาย 0 ครั้งจะไม่กลับมา (เห็นได้ชัดว่าพวกเขาไม่ได้อยู่ในตารางนั้น)

การปรับแต่งคำสั่งเพื่อรับ person_id จากตารางบุคคลทำให้ฉันมีบางสิ่งเช่น:

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;

อย่างไรก็ตามสิ่งนี้จะยังคงส่งคืนเฉพาะ person_id ที่มีการนัดหมายไม่ใช่สิ่งที่ฉันต้องการซึ่งเป็นการส่งคืนกับบุคคลที่มีการนัดหมาย 0 ครั้ง!

ข้อเสนอแนะใด ๆ กรุณา?


1
จะทำอย่างไรถ้าฉันอยากได้ศูนย์ | 0 เป็นผลลัพธ์ในตารางเดียว ฉันมีตาราง vm_tool_licenses และแบบสอบถามเป็นเหมือนด้านล่าง select vm_tool_id, count (vm_tool_license_active) จากกลุ่ม vm_tool_licenses โดย vm_tool_license_active, vm_tool_id มี vm_tool_license_active = false`
Narendra

คำตอบ:


101

คุณต้องการการรวมภายนอกสำหรับสิ่งนี้ (และคุณต้องใช้คนเป็นตาราง "ขับรถ")

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person 
  LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;

เหตุผลที่ใช้งานได้คือการเข้าร่วมด้านนอก (ด้านซ้าย) จะกลับมาNULLสำหรับบุคคลที่ไม่ได้นัดหมาย ฟังก์ชันการรวมcount()จะไม่นับNULLค่าดังนั้นคุณจะได้ศูนย์

หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการรวมภายนอกนี่คือบทช่วยสอนที่ดี: http://sqlzoo.net/wiki/Using_Null


แต่ถ้าบางฟิลด์ของการนัดหมายไม่เป็นโมฆะ (ในนิยามตาราง)?
Lior Yehezkely

@LiorYehezkely: "บางคอลัมน์" ไม่สำคัญ count () ใช้คอลัมน์เข้าร่วม หากไม่เป็นโมฆะจะมีการนัดหมายที่ควรนับ
a_horse_with_no_name

21

คุณต้องใช้LEFT JOINแทนINNER JOIN

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person 
LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;

1
GROUP BY ดูเหมือนจะพิมพ์ผิดในคำถามเดิมเนื่องจากตารางไม่รวมอยู่ในคำค้นหา
Joachim Isaksson

7

หากคุณทำการรวมภายนอก (ด้วยจำนวนนับ) จากนั้นใช้ผลลัพธ์นี้เป็นตารางย่อยคุณจะได้ 0 ตามที่คาดไว้ (ด้วยฟังก์ชัน nvl)

เช่น:

select P.person_id, nvl(A.nb_apptmts, 0) from 
(SELECT person.person_id
FROM person) P
LEFT JOIN 
(select person_id, count(*) as nb_apptmts
from appointment 
group by person_id) A
ON P.person_id = A.person_id

5

ใช้เข้าร่วมเพื่อรับ 0 นับในผลลัพธ์โดยใช้ GROUP BY

เพียงแค่ 'เข้าร่วม' จะเข้าร่วมภายในใน MS SQL ดังนั้นไปซ้ายหรือขวาเข้าร่วม

หากตารางที่มีคีย์หลักถูกกล่าวถึงก่อนใน QUERY ให้ใช้ LEFT join else RIGHT join

เช่น:

select WARDNO,count(WARDCODE) from MAIPADH 
right join  MSWARDH on MSWARDH.WARDNO= MAIPADH.WARDCODE
group by WARDNO

.

select WARDNO,count(WARDCODE) from MSWARDH
left join  MAIPADH on MSWARDH.WARDNO= MAIPADH.WARDCODE group by WARDNO

จับกลุ่มจากตารางที่มีคีย์หลักและนับจากตารางอื่นที่มีรายการ / รายละเอียดจริง


2

หากต้องการเปลี่ยนแปลงข้อความค้นหาเดิมของคุณให้น้อยลงคุณสามารถเปลี่ยนการเข้าร่วมเป็นการRIGHTเข้าร่วมได้

SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
RIGHT JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;

สิ่งนี้สร้างขึ้นจากคำตอบที่เลือก แต่เนื่องจากการรวมภายนอกเป็นไปในRIGHTทิศทางจึงต้องเพิ่มคำเพียงคำเดียวและเปลี่ยนแปลงน้อยลง - เพียงจำไว้ว่ามันอยู่ที่นั่นและบางครั้งอาจทำให้การสืบค้นอ่านง่ายขึ้นและต้องการการสร้างใหม่น้อยลง


0

ปัญหาของการเข้าร่วม LEFT คือหากไม่มีการนัดหมายจะยังคงส่งคืนหนึ่งแถวด้วยค่าว่างซึ่งเมื่อรวมโดย COUNT จะกลายเป็น 1 และจะปรากฏว่าบุคคลนั้นมีการนัดหมายหนึ่งครั้งเมื่อไม่มีการนัดหมายจริง ฉันคิดว่าสิ่งนี้จะให้ผลลัพธ์ที่ถูกต้อง:

SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;

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