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.