2010-02-01 4 views
34

J'ai besoin de récupérer la première ligne supérieure de chaque ensemble d'enregistrements dupliqués de la table donnée ci-dessous. Je dois utiliser cette requête dans la vueObtenir le premier enregistrement du haut à partir des enregistrements en double n'ayant pas d'identité unique

s'il vous plaît pas de table temporaire comme je l'ai déjà fait en ajoutant la colonne d'identité et la fonction min et le groupe par. J'ai besoin de solution sans table temporaire ou variable de table

Ceci est juste un exemple de données. Original a 1000s des enregistrements dans la table et j'ai besoin résultat juste de haut 1000 ne peut donc pas utiliser distincts

J'utilise SQL Server 2005

alt text http://img686.imageshack.us/img686/42/duplicate.png

Merci.

+11

+1 pour prendre tout le temps de faire la maquette de l'écran entier! Je souhaite que plus de gens mettent autant d'efforts dans leurs questions. – Aaronaught

+0

Votre lien d'image est mort. :/ –

Répondre

6

La réponse dépend spécifiquement de ce que vous entendez par les «1000 meilleurs dossiers distincts».

Si vous voulez dire que vous voulez retourner dans la plupart des 1000 dossiers distincts, quel que soit le nombre de doublons sont dans le tableau, puis écrire ceci:

SELECT DISTINCT TOP 1000 id, uname, tel 
FROM Users 
ORDER BY <sort_columns> 

Si vous voulez seulement recherche le premier 1000 lignes de la table, et le retour potentiellement beaucoup moins de 1000 lignes distinctes, alors vous l'écrire avec un sous-requête ou CTE, comme ceci:

SELECT DISTINCT * 
FROM 
(
    SELECT TOP 1000 id, uname, tel 
    FROM Users 
    ORDER BY <sort_columns> 
) u 

le ORDER BY est bien sûr facultative si vous n » t vous souciez des enregistrements que vous renvoyez.

1

Est-ce que SELECT DISTINCT ne aide pas? Je suppose que cela retournerait le résultat que vous voulez.

+1

+1 Correct, pour avoir besoin de sortie pour une entrée donnée :-) – gbn

+0

Désolé, je n'ai pas mentionné dans ma question Ceci est juste des données d'échantillon. L'original a 1000s d'enregistrements dans la table et je dois juste le résultat du top 1000 donc je ne peux pas utiliser ** distinct ** – Kashif

1

En utilisant DISTINCT devrait le faire:

SELECT DISTINCT id, uname, tel 
FROM YourTable 

Bien que vous pourriez vraiment faire d'avoir une clé primaire sur la table, un moyen d'identifier de manière unique chaque enregistrement. Je considérerais coller une colonne d'IDENTITÉ sur la table

+0

Désolé je n'ai pas mentionné dans ma question Ceci est juste des données d'échantillon. Original a 1000s d'enregistrements dans la table et je dois juste résultat du top 1000 donc ne peux pas utiliser ** distinct ** – Kashif

1

YNotre meilleur pari est de corriger la conception de base de données et d'ajouter la colonne d'identiotie à la table. Pourquoi avez-vous une table sans un en premier lieu? Surtout un avec des enregistrements en double! Il est clair que la base de données elle-même doit être redessinée.

Et pourquoi avez-vous cela dans une vue, pourquoi votre solution avec la table temporaire n'est-elle pas une solution valide? Les vues ne sont généralement pas une bonne chose à faire pour une base de données parfaitement sympa.

+0

Vous avez raison MAIS s'il vous plaît dites-moi 1) comment puis-je convaincre mon gestionnaire qui ont besoin de cette solution dans View. 2) J'ai la conception db du client et je dois coller avec cette conception. – Kashif

1

Vous pouvez essayer ce qui suit:

  1. Créer une vue qui sélectionne simplement toutes les colonnes de la table originale mais d'ajouter une colonne numérique supplémentaire dont la valeur augmente avec chaque enregistrement \ ligne. Vous devrez peut-être faire de cette colonne une colonne non entière (par exemple, une décimale et l'incrémenter de 1,00 pour chaque enregistrement à utiliser dans l'instruction SQL RANK()). Ajoutez également une autre colonne (par exemple 'RecordRank') pour contenir les valeurs rangées calculées pour toutes les colonnes à l'aide de la clause RANK() OVER SQL pour créer des valeurs pour cette colonne - voir les références ci-dessous.L'instruction RANK vous permet de partitionner les enregistrements, puis d'ordonner chaque enregistrement de partition en fonction des valeurs de l'ordre par colonne (utilisez la colonne avec les valeurs croissantes de l'étape 1 pour votre commande). Vous utilisez les colonnes avec des données identiques dans la clause de partition afin que tous ces doublons similaires soient partitionnés ou regroupés, puis classés par les valeurs dans la colonne supplémentaire (ordre par colonne de l'étape 1).

    http://msdn.microsoft.com/en-us/library/ms189461.aspx

3, Après avoir créé avec succès la vue ci-dessus, il suffit d'écrire une autre vue de sélectionner uniquement les enregistrements avec « RecordRank » = 1

Cela devrait choisir une seule de chaque enregistrement des doublons ou des partitions.

Hope this helps - malcom Sankoh

11

Trouver tous les produits qui ont été commandés 1 fois ou plus ... (genre de dossiers en double)

SELECT DISTINCT * from [order_items] where productid in 
(SELECT productid 
    FROM [order_items] 
    group by productid 
    having COUNT(*)>0) 
order by productid 

Pour sélectionner le dernier inséré de ceux .. .

SELECT DISTINCT productid, MAX(id) OVER (PARTITION BY productid) AS LastRowId from [order_items] where productid in 
(SELECT productid 
    FROM [order_items] 
    group by productid 
    having COUNT(*)>0) 
order by productid 
+2

Cela aurait dû être la bonne réponse acceptée – Fandango68

1

Voici deux solutions, j'utilise SQL server Oracle:

1) à l'aide sur l'article:

with org_table as 
(select 1 id, 'Ali' uname 
    from dual 
    union 
    select 1, 'June' 
    from dual 
    union 
    select 2, 'Jame' 
    from dual 
    union 
    select 2, 'July' from dual) 
select id, uname 
    from (select a.id, 
       a.uname, 
       ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY a.id) AS freq 

      from org_table a) 
where freq = 1 

2) Utilisation de sous-requête:

with org_table as 
(select 1 id, 'Ali' uname 
    from dual 
    union 
    select 1, 'June' 
    from dual 
    union 
    select 2, 'Jame' 
    from dual 
    union 
    select 2, 'July' from dual) 

select a.id, 
     (select b.uname 
      from org_table b 
     where b.id = a.id 
      and rownum = 1) 
    from (select distinct id from org_table) a 
6

Parfois, vous pouvez utiliser la croix APPLIQUER opérateur comme ceci:

select distinct result.* from data d 
cross apply (select top 1 * from data where data.Id = d.Id) result 

Dans cette requête I besoin de choisir seulement le premier de nombreux doublons qui se produisent naturellement dans mes données. Cela fonctionne sur les bases de données SQL Server 2005+.

+2

Cela fonctionne comme un charme! – MJ33

+0

Merci. Cela a résolu un problème récurrent assez gros que nous avons eu avec des données en double. – NotMe

Questions connexes