วิธีการเลือกแถวแรกจากการเข้าร่วมที่ส่งกลับหลายแถวในคีย์หลัก


15

สิ่งนี้เกี่ยวข้องกับคำถามนี้: การรวมผลลัพธ์หลาย ๆ ตารางเข้าด้วยกันเป็นแถว

ฉันมีสองตารางที่ฉันเข้าร่วม พวกเขาแบ่งปันกุญแจ ตารางบุคคลมีชื่อหนึ่งชื่อต่อคีย์หลัก แต่ตารางอีเมลนั้นมีหลายอีเมลต่อ 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;

3
อีเมลแรกหมายถึงอะไร เกณฑ์การเรียงลำดับแบบใดที่กำหนดว่า "แรก"
คิว Mann

1
คุณลอง 1 อันดับแรกหรือไม่
Racer SQL

3
คุณใช้ DBMS รุ่นใดอยู่ Postgres? ออราเคิล?
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
'A' คืออะไร มันเป็นชื่อย่อของชื่อตารางหรือไม่?
normandantzig

2
@normandantzig นั่นเป็นนามแฝง
เบคอน Bits

1
1. ) คุณใช้นามแฝงว่าทั้งสองตารางของฉันโดยใช้จาก (เลือก Person.PersonName, Email.Email, ROW_NUMBER () OVER (พาร์ทิชันโดยบุคคล ID การสั่งซื้อทางอีเมล) AS 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
'P' เป็นนามแฝงสำหรับบุคคล มันเป็นไปตามประกาศตารางในอนุประโยค
คิว Mann

1
@normandantzig ทั้งสองใช้ได้ใน SQL Server ในสถานการณ์ส่วนใหญ่
เบคอนบิตส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.