วิธีการเลือกทุกแถวที่ค่าคอลัมน์ไม่แตกต่างกัน


154

ฉันต้องเรียกใช้คำสั่ง select ที่ส่งคืนแถวทั้งหมดที่ค่าของคอลัมน์ไม่ชัดเจน (เช่น EmailAddress)

ตัวอย่างเช่นหากตารางมีลักษณะดังนี้:

CustomerName     EmailAddress
Aaron            aaron@gmail.com
Christy          aaron@gmail.com
Jason            jason@gmail.com
Eric             eric@gmail.com
John             aaron@gmail.com

ฉันต้องการแบบสอบถามเพื่อส่งคืน:

Aaron            aaron@gmail.com
Christy          aaron@gmail.com
John             aaron@gmail.com

ฉันได้อ่านบทความจำนวนมากและลองใช้ข้อความค้นหาต่าง ๆ เพื่อประโยชน์ แบบสอบถามที่ฉันเชื่อว่าควรใช้งานได้ด้านล่าง มีคนแนะนำทางเลือกอื่นหรือบอกฉันว่าอาจมีอะไรผิดปกติในการสืบค้นของฉัน

select EmailAddress, CustomerName from Customers
group by EmailAddress, CustomerName
having COUNT(distinct(EmailAddress)) > 1

คำตอบ:


263

สิ่งนี้เร็วกว่าEXISTSวิธีการอย่างมาก:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)

1
เฮ้ฉันรู้ว่าคำตอบนี้มีอายุ 7 ปี แต่ถ้าคุณยังอยู่ใกล้ ๆ คุณจะอธิบายได้ไหมว่ามันทำงานอย่างไร แก้ไขปัญหาของฉันเช่นกัน!
Lou

4
การใช้HAVINGที่นี่แทนที่จะเป็นวินาทีSELECT...WHEREทำให้นี่เป็นแบบสอบถามเดียวแทนที่จะเป็นตัวเลือกที่สองซึ่งเรียกใช้งานการเรียกที่สองSELECT...WHEREหลายครั้ง ดูเพิ่มเติมได้ที่นี่: stackoverflow.com/q/9253244/550975
Serj Sagan

ฉันได้รับ[EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionข้อผิดพลาดที่น่าอับอาย เป็นเพียงการแก้ไข - แก้ไขsql_mode?
Volodymyr Bobyr

[EmailAddress]อยู่ในGROUP BYข้อ
Serj Sagan

51

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

aaron and aaron@gmail.com
christy and aaron@gmail.com
john and aaron@gmail.com

จะถือว่าเป็น 3 กลุ่มที่แตกต่างกันค่อนข้างทั้งหมดอยู่ใน 1 กลุ่มเดียว

กรุณาใช้แบบสอบถามตามที่ระบุด้านล่าง:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)

21
ฉันชอบที่คุณยังมีคำอธิบายเกี่ยวกับสิ่งที่ผิดกับแบบสอบถามต้นฉบับซึ่งแตกต่างจากคำตอบที่ยอมรับ

12

เกี่ยวกับ

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)

11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1

การปรับปรุงเล็กน้อยเพื่อแสดงการนับเป็น "dups": เลือก CustomerName, นับ (1) เป็น dups จากกลุ่มลูกค้าโดย CustomerName ที่มีการนับ (1)> 1`
DynamicDan

8

เพื่อความสนุกนี่เป็นอีกวิธีหนึ่ง:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1

1
+1 สำหรับเวอร์ชัน CTE เราไม่ควรทำซ้ำตัวเองในรหัสทำไมทำซ้ำตัวเองใน SQL ถ้าเราไม่ต้องอีกต่อไป
yzorg

1
ฉันใช้ _count สำหรับคอลัมน์จำนวน (เกินจำนวน) ฉันใช้ขีดเส้นใต้อย่างสม่ำเสมอเมื่อคอลัมน์เกิดการชนกับคำหลัก SQL เช่น _default, _type, _sum ฯลฯ
yzorg

4

แทนที่จะใช้การสืบค้นย่อยในกรณีที่เงื่อนไขซึ่งจะเพิ่มเวลาการสืบค้นที่บันทึกมีขนาดใหญ่

ฉันขอแนะนำให้ใช้ Inner Join เป็นตัวเลือกที่ดีกว่าสำหรับปัญหานี้

พิจารณาตารางเดียวกันนี้อาจให้ผลลัพธ์

SELECT EmailAddress, CustomerName FROM Customers as a 
Inner Join Customers as b on a.CustomerName <> b.CustomerName and a.EmailAddress = b.EmailAddress

เพื่อผลลัพธ์ที่ดียิ่งขึ้นฉันขอแนะนำให้คุณใช้CustomerIDหรือฟิลด์ที่ไม่ซ้ำกันของตารางของคุณ การทำซ้ำCustomerNameเป็นไปได้


-2

มีการเปลี่ยนแปลงเล็กน้อยเพื่อค้นหาแถวที่ไม่ชัดเจน

SELECT EmailAddress, CustomerName FROM Customers WHERE EmailAddress NOT IN
(SELECT EmailAddress FROM Customers GROUP BY EmailAddress HAVING COUNT(*) > 1)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.