ฉันจะค้นหารายการที่ซ้ำกันในหลายคอลัมน์ได้อย่างไร


102

ดังนั้นฉันต้องการทำบางอย่างเช่นโค้ด sql ด้านล่างนี้:

select s.id, s.name,s.city 
from stuff s
group by s.name having count(where city and name are identical) > 1

ในการสร้างสิ่งต่อไปนี้ (แต่ไม่สนใจที่ที่จะจับคู่เฉพาะชื่อหรือเมืองเท่านั้นต้องอยู่ในคอลัมน์ทั้งสอง):

id      name  city   
904834  jim   London  
904835  jim   London  
90145   Fred  Paris   
90132   Fred  Paris
90133   Fred  Paris

คำตอบ:


140

ซ้ำidสำหรับคู่nameและcity:

select s.id, t.* 
from [stuff] s
join (
    select name, city, count(*) as qty
    from [stuff]
    group by name, city
    having count(*) > 1
) t on s.name = t.name and s.city = t.city

โปรดทราบว่าหากมีอย่างใดอย่างหนึ่งnameหรือcityมีnullก็จะไม่สามารถรายงานในแบบสอบถามภายนอกได้ แต่จะถูกจับคู่ในคำค้นหาภายใน
Adam Parkin

3
หากค่าสามารถมีได้null(เว้นแต่ฉันจะขาดบางอย่าง) คุณต้องเปลี่ยนเป็นCROSS JOIN(ผลิตภัณฑ์คาร์ทีเซียนเต็มรูปแบบ) จากนั้นเพิ่มWHEREอนุประโยคเช่น:WHERE ((s.name = t.name) OR (s.name is null and t.name is null)) AND ((s.city = t.city) OR (s.city is null and t.city is null))
Adam Parkin

62
 SELECT name, city, count(*) as qty 
 FROM stuff 
 GROUP BY name, city HAVING count(*)> 1

คำตอบที่สะอาดที่สุด
Repcak

ด้วยเหตุนี้คุณจึงไม่สามารถทราบ id ของแต่ละบรรทัดได้
Juan.Queiroz

10

บางอย่างเช่นนี้จะทำเคล็ดลับ ไม่รู้เกี่ยวกับประสิทธิภาพดังนั้นทำการทดสอบบางอย่าง

select
  id, name, city
from
  [stuff] s
where
1 < (select count(*) from [stuff] i where i.city = s.city and i.name = s.name)

7

การใช้count(*) over(partition by...)เป็นวิธีที่ง่ายและมีประสิทธิภาพในการค้นหาการทำซ้ำที่ไม่ต้องการในขณะที่ยังแสดงรายการแถวที่ได้รับผลกระทบและคอลัมน์ที่ต้องการทั้งหมด:

SELECT
    t.*
FROM (
    SELECT
        s.*
      , COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
    FROM stuff s
    ) t
WHERE t.qty > 1
ORDER BY t.name, t.city

ในขณะที่เวอร์ชัน RDBMS ล่าสุดรองรับcount(*) over(partition by...) MySQL V 8.0แนะนำ "ฟังก์ชันหน้าต่าง" ดังที่แสดงด้านล่าง (ใน MySQL 8.0)

CREATE TABLE stuff(
   id   INTEGER  NOT NULL
  ,name VARCHAR(60) NOT NULL
  ,city VARCHAR(60) NOT NULL
);
INSERT INTO stuff(id,name,city) VALUES 
  (904834,'jim','London')
, (904835,'jim','London')
, (90145,'Fred','Paris')
, (90132,'Fred','Paris')
, (90133,'Fred','Paris')

, (923457,'Barney','New York') # not expected in result
;
SELECT
    t.*
FROM (
    SELECT
        s.*
      , COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
    FROM stuff s
    ) t
WHERE t.qty > 1
ORDER BY t.name, t.city
    id | ชื่อ | เมือง | จำนวน
-----: | : --- | : ----- | -:
 90145 | เฟรด | ปารีส | 3
 90132 | เฟรด | ปารีส | 3
 90133 | เฟรด | ปารีส | 3
904834 | จิม | ลอนดอน | 2
904835 | จิม | ลอนดอน | 2

db <> ซอที่นี่

ฟังก์ชันหน้าต่าง ขณะนี้ MySQL สนับสนุนฟังก์ชันหน้าต่างที่สำหรับแต่ละแถวจากคิวรีทำการคำนวณโดยใช้แถวที่เกี่ยวข้องกับแถวนั้น ซึ่งรวมถึงฟังก์ชันต่างๆเช่น RANK (), LAG () และ NTILE () นอกจากนี้ฟังก์ชันการรวมที่มีอยู่หลายฟังก์ชันสามารถใช้เป็นฟังก์ชันหน้าต่างได้ ตัวอย่างเช่น SUM () และ AVG () สำหรับข้อมูลเพิ่มเติมโปรดดูมาตรา 12.21“ฟังก์ชั่นหน้าต่าง”


4

เกมในโพสต์นี้ช้าไปหน่อย แต่ฉันพบว่าวิธีนี้ค่อนข้างยืดหยุ่น / มีประสิทธิภาพ

select 
    s1.id
    ,s1.name
    ,s1.city 
from 
    stuff s1
    ,stuff s2
Where
    s1.id <> s2.id
    and s1.name = s2.name
    and s1.city = s2.city

2

คุณต้องเข้าร่วมด้วยตนเองและจับคู่ชื่อและเมือง จากนั้นจัดกลุ่มตามจำนวน

select 
   s.id, s.name, s.city 
from stuff s join stuff p ON (
   s.name = p.city OR s.city = p.name
)
group by s.name having count(s.name) > 1

ล้มเหลวใน SQL Server: คอลัมน์ที่ไม่รวมทั้งหมดต้องอยู่ใน GROUP BY
gbn

0

ด้วยตารางการแสดงละครที่มี 70 คอลัมน์และมีเพียง 4 รายการที่แสดงถึงรายการที่ซ้ำกันรหัสนี้จะส่งคืนคอลัมน์ที่กระทำผิด:

SELECT 
    COUNT(*)
    ,LTRIM(RTRIM(S.TransactionDate)) 
    ,LTRIM(RTRIM(S.TransactionTime))
    ,LTRIM(RTRIM(S.TransactionTicketNumber)) 
    ,LTRIM(RTRIM(GrossCost)) 
FROM Staging.dbo.Stage S
GROUP BY 
    LTRIM(RTRIM(S.TransactionDate)) 
    ,LTRIM(RTRIM(S.TransactionTime))
    ,LTRIM(RTRIM(S.TransactionTicketNumber)) 
    ,LTRIM(RTRIM(GrossCost)) 
HAVING COUNT(*) > 1

.

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