Як вибрати перший рядок із з'єднання, який повертає кілька рядків у первинному ключі


15

Це пов’язано з цим питанням: Об’єднання декількох таблиць призводить до повторень

У мене є дві таблиці, до яких я приєднуюся. Вони поділяють ключ. Таблиця осіб має одне ім’я на первинний ключ, але в таблиці електронних повідомлень є кілька електронних листів на personId. Я хочу показати лише перший електронний лист на людину. Зараз я отримую кілька рядків на людину, оскільки вони мають кілька електронних листів. Я запускаю SQL-Server 2005.

EDIT: Це T-SQL. Перший електронний лист - це буквально перший рядок електронної пошти на людину.

Редагувати 2: Перший електронний лист, як я бачу, це буде перший рядок електронної пошти, який відображається під час з'єднання, коли SQL працює за допомогою запиту. Мені неважливо, який електронний лист з’являється. Тільки те, що з’являється не більше одного електронного листа. Я сподіваюся, що це стане зрозумілішим.

Table1: Person
Table2: Email

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

3
Що ви маєте на увазі під першим електронним листом? Які критерії сортування визначають "перше"?
Черга Манна

1
ви спробували топ-1?
гонщик 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
Що таке "А"? Це абревіатура назви таблиці?
normandantzig


1
1.) Чи були ви псевдонімом обох моїх таблиць за допомогою (Виберіть Person.PersonName, Email.Email, ROW_NUMBER () НАД (ПАРТІЯ ПО Person.ID ЗАМОВЛЕННЯ ПО Email.Email) ЯК RN Від особи, що залишилась, приєднайтесь до Person.ID = Email.PersonId) A і 2.), щоб ви могли посилатися на обидва стовпці, використовуючи A як таблицю?
normandantzig

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

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
Що таке 'P'. Це абревіатура назви таблиці?
normandantzig

1
"Р" - псевдонім для Особи. З цього випливає декларація таблиці в пункті FROM.
Черга Манна

1
@normandantzig Обидва дійсні в SQL Server у більшості ситуацій.
Беконні шматочки
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.