Как выбрать первую строку в объединении, которое возвращает несколько строк в первичном ключе

15

Это связано с этим вопросом: объединение нескольких таблиц приводит к дублированию строк

У меня есть две таблицы, к которым я присоединяюсь. Они разделяют ключ. Таблица person имеет одно имя на первичный ключ, но таблица email имеет несколько электронных писем на personId. Я хочу показать только первое письмо на человека. В настоящее время я получаю несколько строк на человека, потому что у них есть несколько электронных писем. Я использую SQL-Server 2005.

РЕДАКТИРОВАТЬ: Это T-SQL. Первое письмо - это буквально первая строка на человека.

Изменить 2: Первое электронное письмо, как я вижу, будет первой строкой электронного письма, которая будет отображаться в соединении, когда SQL обрабатывает запрос. Мне не важно, какое письмо появляется. Только то, что появляется не более одного электронного письма. Я надеюсь, что это проясняет ситуацию.

Table1: Person
Table2: Email

Select Person.PersonName, Email.Email
From person 
left join on Person.ID=Email.PersonId;
normandantzig
источник
3
Что вы подразумеваете под «первым» письмом? Какой критерий сортировки определяет «первый»?
Очередь Манн
1
ты пробовал топ 1?
Racer SQL
3
Какую СУБД вы используете? Postgres? Oracle?
a_horse_with_no_name
3
«Первая строка электронной почты на человека» на самом деле не говорит нам ничего. «Первый» по каким критериям? Таблицы SQL не имеют внутреннего порядка.
ypercubeᵀᴹ
5
Ну, это один действительный критерий: «Мне все равно, какой ряд, только один».
ypercubeᵀᴹ

Ответы:

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
Что такое «А»? Это сокращение имени таблицы?
Норманданциг
2
@normandantzig Это псевдоним .
Бит Бекон
1
1.) Использовали ли вы обе псевдонимы для обеих моих таблиц, используя From (Выберите Person.PersonName, Email.Email, ROW_NUMBER () OVER (PARTITION BY Person.ID ORDER BY Email.Email) AS RN От лица, оставленного присоединиться к Person.ID = Email.PersonId) A и 2.) чтобы вы могли ссылаться на оба столбца, используя A в качестве таблицы?
Норманданциг
4
То, что находится внутри скобки, называется производной таблицей . Это допустимая таблица, так же как и базовые таблицы, но ее время жизни только на время выполнения запроса. У него должно быть имя (или псевдоним), и @sabin решил его назвать A. Эта таблица имеет 3 столбца (PersonName, Email, RN) и вне скобок, вы можете использовать так A.Emailже, как вы можете использовать tablename.columnnameдля любой другой таблицы в вашем коде.
ypercubeᵀᴹ
13

Я бы использовал внешнее приложение для этого, я считаю его более читабельным.

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

Как это не имеет значения, какой адрес электронной почты появляется. Я думаю, что следующий очень прямой.

Select Person.PersonName,  MIN(Email.Email)
From person 
left join email 
on Person.ID=Email.PersonId
group by Person.Id, Person.PersonName
JGA
источник
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
Что такое «П». Это сокращение имени таблицы?
Норманданциг
1
«P» - это псевдоним человека. Это следует за объявлением таблицы в предложении FROM.
Очередь Манн
1
@normandantzig Оба действительны в SQL Server в большинстве ситуаций.
Бекон Биты