Jak wybrać pierwszy wiersz ze sprzężenia, który zwraca wiele wierszy na klucz podstawowy

15

Jest to związane z tym pytaniem: łączenie wielu tabel powoduje zduplikowanie wierszy

Mam dwa stoły, do których dołączam. Dzielą klucz. Tabela osób ma jedną nazwę na klucz podstawowy, ale tabela e-mail zawiera wiele wiadomości e-mail na identyfikator osoby. Chcę pokazać tylko pierwszy e-mail na osobę. Obecnie otrzymuję wiele wierszy na osobę, ponieważ mają wiele e-maili. Korzystam z SQL-Server 2005.

EDYCJA: To jest T-SQL. Pierwszy e-mail to dosłownie pierwszy wiersz e-maila na osobę.

Edycja 2: Pierwszy e-mail, jak widzę, byłby pierwszym wierszem e-maila, który pojawia się w złączeniu, gdy SQL działa przez zapytanie. Nie ważne, który e-mail się pojawi. Tyle, że nie pokazuje się więcej niż jeden e-mail. Mam nadzieję, że to wyjaśni.

Table1: Person
Table2: Email

Select Person.PersonName, Email.Email
From person 
left join on Person.ID=Email.PersonId;
normandantzig
źródło
3
Co rozumiesz przez „pierwszy” e-mail? Jakie kryteria sortowania określają „pierwszy”?
Kolejka Mann
1
próbowałeś top 1?
Racer SQL
3
Z którego DBMS korzystasz? Postgres? Wyrocznia?
a_horse_w_no_name
3
„Pierwszy wiersz email na osobę” tak naprawdę nie mówi nam nic. „Po pierwsze” według jakich kryteriów? Tabele SQL nie mają właściwej kolejności.
ypercubeᵀᴹ
5
Cóż, to jedno ważne kryterium: „Nie obchodzi mnie, który wiersz, tylko jedno”.
ypercubeᵀᴹ

Odpowiedzi:

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
Sabin Bio
źródło
1
Co to jest „A”? Czy to skrót nazwy tabeli?
normandantzig
2
@normandantzig To alias .
Bacon Bits
1
1.) Czy użyłeś aliasu obu moich tabel przy użyciu opcji Od (wybierz Person.PersonName, Email.Email, ROW_NUMBER () OVER (PARTITION BY Person.ID ORDER BY Email.Email) AS RN Od osoby pozostającej dołącz do Person.ID = Email.PersonId) A i 2.), aby można było odwoływać się do obu kolumn przy użyciu A jako tabeli?
normandantzig
4
To, co znajduje się w nawiasie, nazywa się tabelą pochodną . Jest to poprawna tabela, podobnie jak tabele podstawowe, ale jej żywotność trwa tylko przez czas wykonywania zapytania. Musi mieć nazwę (lub alias), a @sabin postanowił ją nazwać A. Ta tabela ma 3 kolumny (PersonName, Email, RN) i poza nawiasami, możesz używać jej A.Emailtak samo, jak tablename.columnnamekażdej innej tabeli w kodzie.
ypercubeᵀᴹ
13

Użyłbym do tego zewnętrznego zgłoszenia, uważam to za bardziej czytelne.

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;
Pan Magoo
źródło
5

Ponieważ nie ma znaczenia, który e-mail się wyświetla. Myślę, że poniższy jest bardzo bezpośredni.

Select Person.PersonName,  MIN(Email.Email)
From person 
left join email 
on Person.ID=Email.PersonId
group by Person.Id, Person.PersonName
JGA
źródło
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
Kolejka Mann
źródło
1
Co to jest „P”. Czy to skrót nazwy tabeli?
normandantzig
1
„P” to pseudonim Person. Jest zgodny z deklaracją tabeli w klauzuli FROM.
Kolejka Mann
1
@ normormantzig Oba są poprawne w SQL Server w większości sytuacji.
Bacon Bits