Comment sélectionner la première ligne d'une jointure qui renvoie plusieurs lignes sur la clé primaire


15

Ceci est lié à cette question: la jointure de plusieurs tables entraîne des lignes en double

J'ai deux tables que je rejoins. Ils partagent une clé. La table des personnes a un nom par clé primaire mais la table des e-mails a plusieurs e-mails par personId. Je souhaite afficher uniquement le premier e-mail par personne. Actuellement, je reçois plusieurs lignes par personne car elles ont plusieurs e-mails. J'exécute SQL-Server 2005.

EDIT: Ceci est T-SQL. Le premier e-mail est littéralement la première ligne d'e-mail par personne.

Edit 2: Premier e-mail tel que je le vois, ce serait la première ligne d'e-mail qui apparaît dans la jointure pendant que SQL fonctionne via la requête. Peu importe quel e-mail apparaît. Seulement, pas plus d'un e-mail n'apparaît. J'espère que cela le rend plus clair.

Table1: Person
Table2: Email

Select Person.PersonName, Email.Email
From person 
left join on Person.ID=Email.PersonId;

3
Qu'entendez-vous par "premier" e-mail? Quels critères de tri déterminent "d'abord"?
Queue Mann

1
avez-vous essayé le top 1?
Racer SQL

3
Quel SGBD utilisez-vous? Postgres? Oracle?
a_horse_with_no_name

3
La "première ligne d'email par personne" ne nous dit vraiment rien. "D'abord" selon quels critères? Les tables SQL n'ont pas d'ordre inhérent.
ypercubeᵀᴹ

5
Eh bien, c'est un critère valable: "Je me fiche de quelle rangée, juste une".
ypercubeᵀᴹ

Réponses:


18
SELECT
    A.PersonName, A.Email
FROM
        (
        Select Person.PersonName, Email.Email
            ,ROW_NUMBER() OVER(PARTITION BY Person.ID ORDER BY Email.Email) AS RN
        From person 
        left join Email on Person.ID=Email.PersonId
        ) A
WHERE A.RN = 1

1
Qu'est-ce que le «A»? Est-ce une abréviation du nom de la table?
normandantzig

2
@normandantzig C'est un alias .
Bacon Bits

1
1.) Avez-vous alias mes deux tables en utilisant De (Sélectionnez Person.PersonName, Email.Email, ROW_NUMBER () OVER (PARTITION BY Person.ID ORDER BY Email.Email) AS RN From Person left join on Person.ID = Email.PersonId) A et 2.) afin que vous puissiez vous référer aux deux colonnes en utilisant A comme table?
normandantzig

4
Ce qui est à l'intérieur de la parenthèse est appelé une table dérivée . C'est une table valide, tout comme les tables de base, mais sa durée de vie ne concerne que la durée de l'exécution de la requête. Il doit avoir un nom (ou un alias) et @sabin a choisi de le nommer A. Ce tableau comporte 3 colonnes (PersonName, Email, RN) et en dehors des parenthèses, vous pouvez utiliser A.Emailcomme vous pouvez utiliser tablename.columnnamepour toutes les autres tables de votre code.
ypercubeᵀᴹ

13

J'utiliserais une application externe pour cela, je la trouve plus lisible.

Select Person.PersonName, coalesce(Email.Email,'No email found.') as Email
From person 
outer apply (
  select top(1) Email.Email 
  from Email 
  where Person.ID=Email.PersonId
  order by <whatever suits you>
) as Email;

5

Comme peu importe quel e-mail apparaît. Je pense que le suivant est très direct.

Select Person.PersonName,  MIN(Email.Email)
From person 
left join email 
on Person.ID=Email.PersonId
group by Person.Id, Person.PersonName

3
select
  P.PersonID,
  (SELECT TOP 1 E.Email FROM Email E WHERE E.PersonID = P.PersonID ORDER BY <pick your column here>)
from
  Person P

1
Qu'est-ce que le «P». Est-ce une abréviation du nom de la table?
normandantzig

1
'P' est un alias pour Person. Il suit la déclaration de table dans la clause FROM.
Queue Mann

1
@normandantzig Les deux sont valides dans SQL Server dans la plupart des situations.
Bacon Bits
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.