2015-08-26 1 views
2

Je dois trouver enregistrement en double (avec l'identifiant d'enregistrement maître et en double ids record):Comment sélectionner à la fois row_number et count over partition?

select ciid, name from (
select ciid, name, row_number() over (
    partition by related_id, name order by updatedate desc) rn 
) where rn = 1; 

Cela me donne les ID d'enregistrement maître, mais il comprend aussi des enregistrements sans doublons.

Si je

select ciid, name from (
select ciid, name, row_number() over (
    partition by related_id, name order by updatedate desc) rn 
) where rn > 1; 

Cela me reçoit tous les enregistrements en double, mais pas l'enregistrement maître.

Je souhaitais si je fais quelque chose comme:

select ciid, name from (
select ciid, name, row_number() over (
    partition by related_id, name order by updatedate desc 
) rn, count(*) over (
    partition by related_id, name order by updatedate desc 
) cnt 
) where rn = 1 and cnt > 1; 

Mais j'étais inquiet au sujet de la performance, ou même est en train de faire ce que je veux.

Comment puis-je obtenir la fiche uniquement pour les doublons? Veuillez noter que name n'est pas une colonne unique. Seul ciid est unique.

Répondre

0

Je n'ai pas testé (parce que je n'ai pas de données réelles et je suis trop paresseux pour créer quelques-uns), mais il semble quelque chose le long de ces lignes pourrait fonctionner:

with has_duplicates as (
    select related_id, name 
    from yourtable 
    group by related_id, name 
    having count (*) > 1 
), 
with_dupes as (
    select 
    y.ccid, y.name, 
    row_number() over (partition by y.related_id, y.name order by y.updatedate desc) rn 
    from 
    yourtable y, 
    has_duplicates d 
    where 
    y.related_id = d.related_id and 
    y.name = d.name 
) 
select 
    ccid, name 
from with_dupes 
where rn = 1 
1
select ciid, name 
from (
select ciid, name, 
dense_rank() over (partition by related_id, name order by updatedate desc) rn 
from tablename) t 
group by ciid,name 
having count(distinct rn) > 1; 

Éditer: Pour trouver des doublons, pourquoi ne pas le faire.

select x.ciid, x.name, x.updatedate 
from tablename x join 
(
select name, related_id, max(updatedate) as mxdt, count(*) 
from tablename 
group by name, related_id 
having count(*) > 1 
) t 
on x.updatedate = t.mxdt and x.name = t.name 

Vous pouvez faire un group by avec having pour sélectionner uniquement les id ayant plus d'une ligne avec le même numéro de ligne.

+0

Il ne retourne rien ... Est-ce que 'distinct rn' fonctionne? On dirait que rn est différent pour chaque ligne de la partition. – texasbruce

+0

Group By CIID ne retournera rien ... CIID est unique ... – texasbruce

+0

Est-ce que la partie éditée ne marche pas? juste pour trouver des doublons? –

6

Je fini par utiliser la même question dans ma question:

select ciid, name from (
select ciid, name, row_number() over (
    partition by related_id, name order by updatedate desc 
) rn, count(*) over (
    partition by related_id, name desc 
) cnt 
) where rn = 1 and cnt > 1; 

Fonctionne étonnamment bien. L'enregistrement principal est où rn = 1 et les doublons sont où rn> 1. Assurez-vous que count(*) over (partition ..) ne peut pas avoir la clause order by.

+0

En fait, c'est la bonne solution. Ma solution effectue deux analyses de la table, alors que vous effectuez cela avec un seul balayage. Il est tout à fait logique maintenant que je le vois, et j'aurais aimé avoir moi-même trouvé – Hambone

+0

@Hambone Merci .. mais juste pour donner quelques points de toute façon – texasbruce

+0

@texasbruce réponse impressionnante, ne savais pas que vous pouvez utiliser compter sur – VorobeY1326