2008-09-25 14 views
4

Ok J'ai une table qui a des données redondantes et j'essaie d'identifier toutes les lignes qui ont des sous-lignes en double (à défaut d'un meilleur mot). Par sous-lignes, je veux dire en considérant uniquement COL1 et COL2.Quelle est la requête SQL pour lister toutes les lignes ayant 2 sous-lignes de colonne en tant que doublons?

Alors disons que j'ai quelque chose comme ceci:

COL1 COL2 COL3 
--------------------- 
aa  111 blah_x 
aa  111 blah_j 
aa  112 blah_m 
ab  111 blah_s 
bb  112 blah_d 
bb  112 blah_d 
cc  112 blah_w 
cc  113 blah_p 

J'ai besoin d'une requête SQL qui retourne ceci:

COL1 COL2 COL3 
--------------------- 
aa  111 blah_x 
aa  111 blah_j 
bb  112 blah_d 
bb  112 blah_d 

Répondre

8

Est-ce que cela fonctionne pour vous?

select t.* from table t 
left join (select col1, col2, count(*) as count from table group by col1, col2) c on t.col1=c.col1 and t.col2=c.col2 
where c.count > 1 
+0

C'est une bonne réponse. Je pense que le mien va courir plus vite sur une grande base de données, mais je laisserais cela à un administrateur de base de données pour décider. –

+0

La jointure à gauche n'est pas nécessaire en raison des critères sur le côté droit. –

+0

Regarde plus lentement qu'une solution basée sur une fonction analytique pour moi. –

4

Inscrivez-vous sur vous-même comme ceci:

SELECT a.col3, b.col3, a.col1, a.col2 
FROM tablename a, tablename b 
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.col3 != b.col3 

Si vous utilisez postgresql, vous pouvez utiliser l'oid pour le rendre moins de résultats dupliqués, comme ceci:

SELECT a.col3, b.col3, a.col1, a.col2 
FROM tablename a, tablename b 
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.col3 != b.col3 
    AND a.oid < b.oid 
2

Ne pas avoir une base de données à portée de main pour tester, mais je pense que cela devrait fonctionner ...

select 
    * 
from 
    theTable 
where 
    col1 in 
    (
    select 
     col1 
    from 
     theTable 
    group by 
     col1||col2 
    having 
     count(col1||col2) > 1 
    ) 
+0

Cela échoue sur SQL Server, car ISN 'col1' 't présent dans la clause GROUP BY. Je suis sûr que cela échouera sur la plupart des autres bases de données SQL. –

2

Ma tentative naïve serait

select a.*, b.* from table a, table b where a.col1 = b.col1 and a.col2 = b.col2 and a.col3 != b.col3; 

mais retournerait toutes les lignes deux fois. Je ne suis pas sûr de savoir comment vous pourriez le restreindre en le renvoyant simplement une fois. Peut-être que s'il y avait une clé primaire, vous pourriez ajouter "et a.pkey < b.pkey".

Comme je l'ai dit, ce n'est pas élégant et il y a probablement une meilleure façon de le faire.

5

Avec les données que vous avez énumérées, votre requête n'est pas possible. Les données sur les lignes 5 & 6 ne sont pas distinctes à l'intérieur de lui-même.

En supposant que votre table est nommée 'quux', si vous commencez avec quelque chose comme ceci:

SELECT a.COL1, a.COL2, a.COL3 
FROM quux a, quux b 
WHERE a.COL1 = b.COL1 AND a.COL2 = b.COL2 AND a.COL3 <> b.COL3 
ORDER BY a.COL1, a.COL2 

Vous vous retrouverez avec cette réponse:

COL1 COL2 COL3 
--------------------- 
aa  111 blah_x 
aa  111 blah_j 

C'est parce que les lignes 5 & 6 ont les mêmes valeurs pour COL3. Toute requête qui renvoie les deux lignes 5 & 6 retournera également des doublons de TOUTES les lignes de cet ensemble de données.

D'autre part, si vous avez une clé primaire (ID), vous pouvez utiliser cette requête à la place:

SELECT a.COL1, a.COL2, a.COL3 
FROM quux a, quux b 
WHERE a.COL1 = b.COL1 AND a.COL2 = b.COL2 AND a.ID <> b.ID 
ORDER BY a.COL1, a.COL2 

[Edité pour simplifier la clause WHERE]

Et vous « ll obtenir les résultats que vous voulez:

COL1 COL2 COL3 
--------------------- 
aa  111 blah_x 
aa  111 blah_j 
bb  112 blah_d 
bb  112 blah_d 

Je viens de tester cela sur SQL Server 2000, mais vous devriez voir les mêmes résultats sur une base de données SQL moderne.

blorgbeard m'a prouvé wrong - bon pour lui!

2

Quelque chose comme cela devrait fonctionner: En général,

SELECT a.COL1, a.COL2, a.COL3 
FROM YourTable a 
JOIN YourTable b ON b.COL1 = a.COL1 AND b.COL2 = a.COL2 AND b.COL3 <> a.COL3 

la clause JOIN devrait inclure toutes les colonnes que vous envisagez de faire partie d'un « double » (COL1 et COL2 dans ce cas), et au moins une colonne (ou autant qu'il en faut) pour éliminer une ligne se rejoignant (COL3, dans ce cas).

2

Ceci est assez similaire à l'auto-jointure, sauf qu'il n'aura pas les doublons.

select COL1,COL2,COL3 
from theTable a 
where exists (select 'x' 
       from theTable b 
       where a.col1=b.col1 
       and a.col2=b.col2 
       and a.col3<>b.col3) 
order by col1,col2,col3 
0

select COL1, COL2, COL3

de la table

groupe par COL1, COL2, COL3

ayant count (*)> 1

+0

Cela ne fonctionne pas. Examinez la ligne blah_x dans la question pour comprendre pourquoi. –

0

Oubliez jointures - utilisation une fonction analytique:

select col1, col2, col3 
from 
(
select col1, col2, col3, count(*) over (partition by col1, col2) rows_per_col1_col2 
from table 
) 
where rows_per_col1_col2 > 1 
+0

Cela ne fonctionne que si votre base de données le supporte. SQL Server 2005 le fait, et probablement Oracle le fait. SQL Server 2000 ne fonctionne pas, MySQL ou PostgresQL non plus. –

+0

Ah, quelque chose de nouveau à apprendre. Devrait-il y avoir une autre clause dans ce document? –

1

Voici comment vous trouvez des doublons. Testé en oracle 10g avec vos données.

select * from TST où (col1, col2) dans (sélectionner col1, col2 du groupe tst par col1, comte col2 ayant (*)> 1)