Come selezionare la prima riga da un join che restituisce più righe sulla chiave primaria


15

Ciò è correlato a questa domanda: l' unione di più tabelle genera righe duplicate

Ho due tavoli a cui mi sto unendo. Condividono una chiave. La tabella persona ha un nome per chiave primaria ma la tabella e-mail ha più e-mail per ID persona. Voglio mostrare solo la prima e-mail a persona. Attualmente ricevo più righe a persona perché hanno più e-mail. Sto eseguendo SQL-Server 2005.

EDIT: questo è T-SQL. La prima email è letteralmente la prima riga di email per persona.

Modifica 2: prima e-mail come vedo sarebbe la prima riga di e-mail che viene visualizzata nel join mentre SQL funziona attraverso la query. Non importa quale email compaia. Solo che non viene visualizzata più di una e-mail. Spero che sia più chiaro.

Table1: Person
Table2: Email

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

3
Cosa intendi per "prima" email? Quali criteri di ordinamento determinano "prima"?
Coda Mann,

1
hai provato la top 1?
Racer SQL,

3
Quale DBMS stai usando? Postgres? Oracolo?
a_horse_with_no_name l'

3
La "prima riga di posta elettronica per persona" non ci dice davvero nulla. "Primo" secondo quali criteri? Le tabelle SQL non hanno un ordine intrinseco.
ypercubeᵀᴹ

5
Bene, questo è un criterio valido: "Non mi interessa quale riga, solo una".
ypercubeᵀᴹ

Risposte:


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
Cos'è la "A"? È un'abbreviazione del nome della tabella?
Normandantzig,

2
@normandantzig Questo è un alias .
Bacon Bits

1
1.) Hai fatto alias entrambi i miei tavoli usando Da (Seleziona Person.PersonName, Email.Email, ROW_NUMBER () OVER (PARTITION BY Person.ID ORDER BY Email.Email) COME RN Da persona lasciata su Person.ID = Email.PersonId) A And 2.) in modo che tu possa fare riferimento a entrambe le colonne usando A come tabella?
Normandantzig,

4
Ciò che è racchiuso tra parentesi è chiamato tabella derivata . È una tabella valida, proprio come le tabelle di base ma la sua durata è solo per la durata dell'esecuzione della query. Deve avere un nome (o alias) e @sabin ha scelto di nominarlo A. Questa tabella ha 3 colonne (PersonName, Email, RN) e al di fuori delle parentesi, puoi usare A.Emailcome puoi usare tablename.columnnameper ogni altra tabella nel tuo codice.
ypercubeᵀᴹ

13

Vorrei utilizzare una domanda esterna per questo, lo trovo più leggibile.

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

Poiché non importa quale e-mail viene visualizzata. Penso che il seguente sia molto diretto.

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
Qual è la 'P'. È un'abbreviazione del nome della tabella?
Normandantzig,

1
'P' è un alias per persona. Segue la dichiarazione della tabella nella clausola FROM.
Coda Mann,

1
@normandantzig Entrambi sono validi in SQL Server nella maggior parte dei casi.
Bacon Bits
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.