So wählen Sie die erste Zeile aus einem Join aus, der mehrere Zeilen auf dem Primärschlüssel zurückgibt


14

Dies hängt mit dieser Frage zusammen: Das Verknüpfen mehrerer Tabellen führt zu doppelten Zeilen

Ich habe zwei Tische, an denen ich teilnehme. Sie teilen einen Schlüssel. Die Personentabelle hat einen Namen pro Primärschlüssel, aber die E-Mail-Tabelle enthält mehrere E-Mails pro Personen-ID. Ich möchte nur die erste E-Mail pro Person anzeigen. Derzeit erhalte ich mehrere Zeilen pro Person, da sie mehrere E-Mails hat. Ich verwende SQL-Server 2005.

EDIT: Dies ist T-SQL. Die erste E-Mail ist buchstäblich die erste E-Mail-Zeile pro Person.

Bearbeiten 2: Erste E-Mail, wie ich sehe, ist die erste E-Mail-Zeile, die im Join angezeigt wird, wenn SQL die Abfrage durcharbeitet. Es ist mir egal, welche E-Mail angezeigt wird. Nur dass nicht mehr als eine E-Mail angezeigt wird. Ich hoffe das macht es klarer.

Table1: Person
Table2: Email

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

3
Was meinst du mit "erster" E-Mail? Welche Sortierkriterien bestimmen "zuerst"?
— Warteschlange Mann

1
Hast du Top 1 ausprobiert?
— Racer SQL

3
Welches DBMS verwenden Sie? Postgres? Orakel?
— a_horse_with_no_name

3
Die "erste E-Mail-Zeile pro Person" sagt uns eigentlich nichts. "Zuerst" nach welchen Kriterien? SQL-Tabellen haben keine inhärente Reihenfolge.
— Ypercubeᵀᴹ

5
Nun, das ist ein gültiges Kriterium: "Es ist mir egal, welche Zeile, nur eine".
— Ypercubeᵀᴹ

Antworten:


17
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
Was ist das "A"? Ist es eine Abkürzung für den Tabellennamen?
— Normandantzig

2
@normandantzig Das ist ein Alias .
— Bacon Bits

1
1.) Haben Sie beide Tabellen mit dem Alias ​​"Von" (Wählen Sie "Person.PersonName", "Email.Email", "ROW_NUMBER") ("PARTITION BY Person.ID ORDER BY Email.Email") als RN From person left join on Person.ID = Email.PersonId) A und 2.) damit Sie mit A als Tabelle auf beide Spalten verweisen können?
— Normandantzig

4
Was sich in der Klammer befindet, wird als abgeleitete Tabelle bezeichnet . Es ist eine gültige Tabelle, genau wie Basistabellen, aber ihre Lebensdauer gilt nur für die Dauer der Abfrageausführung. Es muss einen Namen (oder Alias) haben und @sabin hat ihn benannt A. Diese Tabelle enthält 3 Spalten (PersonName, Email, RN). Außerhalb der Klammern können Sie sie A.Emailgenauso verwenden, wie Sie sie tablename.columnnamefür jede andere Tabelle in Ihrem Code verwenden können.
— Ypercubeᵀᴹ

13

Ich würde dafür eine äußere Bewerbung verwenden, ich finde sie besser lesbar.

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

Da es egal ist, welche E-Mail angezeigt wird. Ich denke, dass der folgende sehr direkt ist.

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
Was ist das "P". Ist es eine Abkürzung für den Tabellennamen?
— Normandantzig

1
'P' ist ein Alias ​​für Person. Es folgt der Tabellendeklaration in der FROM-Klausel.
— Warteschlange Mann

1
@normandantzig Beide sind in den meisten Situationen in SQL Server gültig.
— Bacon Bits
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.