Làm cách nào để tìm các bản sao trên nhiều cột?


98

Vì vậy, tôi muốn làm một cái gì đó giống như mã sql này dưới đây:

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

Để tạo ra thông tin sau, (nhưng bỏ qua vị trí chỉ tên hoặc chỉ kết hợp thành phố, nó phải nằm trên cả hai cột):

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

Câu trả lời:


137

Nhân đôi idcho các cặp namecity:

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

Lưu ý rằng nếu một trong hai namehoặc citychứa null, thì chúng sẽ không được báo cáo trong truy vấn bên ngoài, nhưng sẽ được so khớp trong truy vấn bên trong.
Adam Parkin

3
Nếu các giá trị có thể có thể chứa nullsau đó (trừ khi tôi đang thiếu một cái gì đó), bạn cần phải thay đổi nó thành một CROSS JOIN(sản phẩm Descartes đầy đủ) và sau đó thêm một WHEREkhoản như: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

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

10

Một cái gì đó như thế này sẽ thực hiện thủ thuật. Không biết về hiệu suất, vì vậy hãy thực hiện một số bài kiểm tra.

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

6

Việc sử dụng count(*) over(partition by...)cung cấp một phương tiện đơn giản và hiệu quả để xác định vị trí lặp lại không mong muốn, đồng thời liệt kê tất cả các hàng bị ảnh hưởng và tất cả các cột mong muốn:

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

Trong khi hầu hết các phiên bản RDBMS gần đây hỗ trợ count(*) over(partition by...) MySQL V 8.0 đã giới thiệu "các hàm cửa sổ", như được thấy bên dưới (trong 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 | tên | thành phố | qty
-----: | : --- | : ----- | -:
 90145 | Fred | Paris | 3
 90132 | Fred | Paris | 3
 90133 | Fred | Paris | 3
904834 | jim | Luân Đôn | 2
904835 | jim | Luân Đôn | 2

db <> fiddle here

Các chức năng của cửa sổ. MySQL hiện hỗ trợ các hàm cửa sổ, đối với mỗi hàng từ một truy vấn, thực hiện phép tính bằng cách sử dụng các hàng liên quan đến hàng đó. Chúng bao gồm các hàm như RANK (), LAG () và NTILE (). Ngoài ra, một số hàm tổng hợp hiện có có thể được sử dụng như các hàm cửa sổ; ví dụ, SUM () và AVG (). Để biết thêm thông tin, hãy xem Phần 12.21, “Chức năng cửa sổ” .


3

Trò chơi trên bài đăng này hơi muộn, nhưng tôi thấy cách này khá linh hoạt / hiệu quả

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

Bạn phải tự tham gia các công cụ và kết hợp tên và thành phố. Sau đó nhóm theo số đếm.

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

Thất bại trong SQL Server: tất cả các cột không tổng hợp phải nằm trong GROUP BY
GBN

0

Đưa ra một bảng dàn dựng có 70 cột và chỉ 4 đại diện cho các bản sao, mã này sẽ trả về các cột vi phạm:

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

.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.