web-dev-qa-db-fra.com

Comment sélectionner uniquement les premières lignes pour chaque valeur unique d'une colonne

Disons que j'ai une table d'adresses de clients:

CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave

Dans la table, un client tel que John Smith peut avoir plusieurs adresses .. J'ai besoin de la requête select pour que cette table ne renvoie que la première ligne trouvée où il y a des doublons dans 'CName'. Pour cette table, elle doit renvoyer toutes les lignes sauf la 3ème (ou la 1ère - toutes ces adresses sont acceptables, mais une seule peut être renvoyée). le serveur a déjà vu la valeur de la colonne auparavant?

68
nuit9

Une réponse très simple si vous dites que vous ne vous souciez pas de l'adresse utilisée.

SELECT
    CName, MIN(AddressLine)
FROM
    MyTable
GROUP BY
    CName

Si vous voulez le premier selon, par exemple, une colonne "insérée", c'est une requête différente

SELECT
    M.CName, M.AddressLine,
FROM
    (
    SELECT
        CName, MIN(Inserted) AS First
    FROM
        MyTable
    GROUP BY
        CName
    ) foo
    JOIN
    MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted
105
gbn

En SQL 2k5 +, vous pouvez faire quelque chose comme:

;with cte as (
  select CName, AddressLine,
  rank() over (partition by CName order by AddressLine) as [r]
  from MyTable
)
select CName, AddressLine
from cte
where [r] = 1
21
Ben Thul

Vous pouvez utiliser row_number() pour obtenir le numéro de la ligne. Il utilise la commande over - la clause partition by spécifie quand redémarrer la numérotation et le order by sélectionne les éléments sur lesquels le numéro de ligne doit être commandé. Même si vous avez ajouté un order by à la fin de votre requête, le classement sera conservé dans la commande over lors de la numérotation.

select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1
9
Rizzi Frank

Vous pouvez utiliser la syntaxe row_numer() over(partition by ...) comme suit:

select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1

Cela crée une colonne appelée row, qui est un compteur qui s'incrémente chaque fois qu'il voit la même CName, et indexe ces occurrences par AddressLine. En imposant where row = 1, on peut sélectionner la CName dont AddressLine vient en premier par ordre alphabétique. Si le order by était desc, il choisirait alors la CName dont AddressLine vient en dernier par ordre alphabétique.

4
FatihAkici

Cela vous donnera une ligne de chaque ligne en double. Il vous donnera également les colonnes de type bit, et cela fonctionne au moins dans MS Sql Server. 

(select cname, address 
from (
  select cname,address, rn=row_number() over (partition by cname order by cname) 
  from customeraddresses  
) x 
where rn = 1) order by cname

Si vous voulez trouver tous les doublons à la place, changez simplement rn = 1 en rn> 1 ..__

0
netfed