2013-10-10 2 views
0

Salut J'ai un tableau suivant dit prixSQL affichant des lignes avec des valeurs en double dans 3 lignes

CostID ItemID Level EffectiveFrom EffectiveTo    
6274751 12345 1  12/02/2013 NULL 
6274751 12345 1  13/02/2013 NULL 
6274751 12345 2  12/02/2013 NULL 
6254784 12345 1  12/02/2013 NULL 
6254784 12345 1  13/02/2013 NULL 
6244784 12345 9  12/02/2013 NULL 

Je voudrais être en mesure d'écrire une requête pour trouver les lignes en double en comparant 3 colonnes de CostID '' ItemID » et « niveau » et afficher celles qui sont doublons uniquement

prévue sortie Partie 1

CostID ItemID Level EffectiveFrom EffectiveTo    
6274751 12345 1  12/02/2013 NULL 
6274751 12345 1  13/02/2013 NULL 
6254784 12345 1  12/02/2013 NULL 
6254784 12345 1  13/02/2013 NULL 

une fois que je reçois le résultat ci-dessus et je voudrais mettre à jour la table EffectiveTo de la dernière double rangée

Sortie prévue pour la partie 2

CostID ItemID Level EffectiveFrom EffectiveTo    
6274751 12345 1  12/02/2013 13/02/2013 
6274751 12345 1  13/02/2013 NULL 
6254784 12345 1  12/02/2013 13/02/2013 
6254784 12345 1  13/02/2013 NULL 

J'ai essayé ceci:

{ 
SELECT * 
FROM price 
WHERE ItemID IN 
    ( SELECT ItemID 
      FROM price 
      GROUP BY ItemId   HAVING COUNT(distinct level) > 1 
    ) 
ORDER BY CostID } 

pour la première partie de la requête mais n'a pas pu obtenir les résultats que je veux, toute aide serait très appréciée.

Merci

+0

Quel sql utilisez-vous? –

+0

SQL Server 2005, Merci pour le formatage pour moi – user2865216

+0

Il y en a tellement que vous vouliez déterminer. Soyez précis s'il vous plait. S'il vous plaît fournir votre sortie attendue. –

Répondre

1

Cela vous donnera les lignes en double:

select distinct p.* 
from price p 
join price q 
    on p.CostID = q.CostID 
    and p.ItemID = q.ItemID 
    and p.Level = q.Level 
    and p.EffectiveFrom != q.EffectiveFrom 

La condition p.EffectiveFrom != q.EffectiveFrom est importante car elle arrête toutes les lignes joignant à eux-mêmes. Normalement, vous comparez simplement une colonne d'identifiant pour l'inégalité, mais votre table ne semble pas en avoir.


Pour mettre à jour l'ancienne ligne avec une date de fin appropriée:

update p set 
p.EffectiveTo = dateadd(day, -1, q.EffectiveFrom) 
from price p 
join price q 
    on p.CostID = q.CostID 
    and p.ItemID = q.ItemID 
    and p.Level = q.Level 
    and p.EffectiveFrom < q.EffectiveFrom 

La seule différence avec cette requête est changé l'inégalité à moins que, sélectionnant ainsi la mise à jour uniquement les lignes sont les premiers.

Notez que j'ai soustrait 1 jour à partir de la date la plus récente, donc il n'y a pas de chevauchement.

+0

En utilisant cette requête, j'obtiens beaucoup trop de résultats, si j'ai 41 000 enregistrements sur ma table, après l'exécution de la requête, je reçois 100 000 enregistrements. Tout ce que je voulais voir, c'était quelque chose comme 1.000 enregistrements en double afin que je puisse manuellement exécuter la partie 2. Comme dans mon exemple, j'avais 6 enregistrements et après l'exécution de la requête je voudrais voir les 4 qui sont des doublons. Merci – user2865216

+0

Avez-vous plusieurs (plus de 2) lignes avec les mêmes données clés? – Bohemian

+0

Lorsque j'ai exécuté la deuxième requête, le tableau 'prix' est ambigu – user2865216

0

Celui-ci est un peu long ... mais vous pouvez apporter quelques améliorations.

;WITH cte AS 
(
    SELECT ROW_NUMBER() OVER (PARTITION BY CostID, ItemID, Level ORDER BY CostID, EffectiveFrom) AS RNUM, 
     CostID, 
     ItemID, 
     Level, 
     EffectiveFrom, 
     EffectiveTo 
    FROM @Price 
), 
cteDup AS 
(
    SELECT DISTINCT CostID, ItemID, Level FROM cte WHERE RNUM > 1 
) 
SELECT tt.* FROM @Price tt 
INNER JOIN cteDup cc ON tt.CostID = cc.CostID AND tt.ItemID = cc.ItemID AND tt.Level = cc.Level 

MISE À JOUR: Cela fera une mise à jour directe, pas sûr si cela est ce que vous voulez tho.

;WITH cte AS 
(
    SELECT ROW_NUMBER() OVER (PARTITION BY CostID, ItemID, Level ORDER BY CostID, EffectiveFrom) AS RNUM, 
     CostID, 
     ItemID, 
     Level, 
     EffectiveFrom, 
     EffectiveTo 
    FROM @Price 
) 
UPDATE c1 SET 
    EffectiveTo = c2.EffectiveFrom 
FROM cte c1 
INNER JOIN cte c2 ON c1.CostID = c2.CostID AND c1.ItemID = c2.ItemID AND c1.Level = c2.Level AND c1.RNUM + 1 = c2.RNUM 
+0

Cela me donne le résultat parfaitement, mais ne peut pas mettre à jour une fois que le résultat est affiché. Y at-il une requête de mise à jour pour atteindre la partie 2 sans avoir à faire la partie 1? – user2865216

Questions connexes