複数の列で重複を見つけるにはどうすればよいですか?


98

だから私はこの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

回答:


137

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))
アダム・パーキン

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

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)

6

を使用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 <> fiddle

ウィンドウ関数。 MySQLは、クエリの各行について、その行に関連する行を使用して計算を実行するウィンドウ関数をサポートするようになりました。これらには、RANK()、LAG()、NTILE()などの関数が含まれます。さらに、いくつかの既存の集約関数をウィンドウ関数として使用できるようになりました。たとえば、SUM()やAVG()などです。詳細については、12.21項「ウィンドウ関数」を参照してください。


3

この投稿のゲームには少し遅れましたが、この方法はかなり柔軟で効率的であることがわかりました

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.