我试图使用以下sql语句查询2个表,以尝试返回包含特定id的每个表中的所有记录。
SELECT Phone.Phone, Email.Email FROM Contacts.Phone, Contacts.Email
WHERE Phone.ContactId = :contactId AND Email.ContactId = :contactId
Contacts.Phone
表包含2个给定ID的电话号码,Contacts.Email
包含1个给定ID的电子邮件。使用上面的sql查询,我得到以下行返回。当然,这只是一个例子,我的每个表的结果集的行数都匹配。
Row 1: 555-555-5555 - email@email.com
Row 2: 666-666-6666 - email@email.com
重复发送电子邮件,以便在我尝试获取时填写第二行:
Row 1: 555-555-5555 - email@email.com
Row 2: 666-666-6666 - NULL
我认为我需要使用UNION
以某种方式连接表,但我无法弄清楚如何编写sql语句。另一个选择是执行2个单独的SQL查询,这会更容易,但我认为性能方面更好的是在一个查询中收集我需要的所有数据。
我正在使用MySQL。
答案 0 :(得分:2)
使用left outer join
解决您的问题,如果您使用MS SQL,查询将如下所示:
SELECT
Phone.Phone,
Email.Email
FROM
Contacts.Phone
Left Outer Join Contacts.Email ON Phone.ContactId = Email.ContactId
您的结果如下所示:
Row 1: 555-555-5555 - email@email.com
Row 2: 666-666-6666 - NULL
答案 1 :(得分:1)
首先,我认为:
另一个选择是执行2个单独的SQL查询,这会更容易,但我认为性能明智,在一个查询中收集我需要的所有数据会更好。
有点误导。一个复杂查询和两个简单查询之间的性能差异非常小。也就是说,你建议使用UNION
;如果您确实想要使用单个查询,则可以执行以下操作:
SELECT 'EMAIL', Email.Email
FROM Contacts.Email
WHERE Email.ContactId = :contactId
UNION ALL
SELECT 'PHONE', Phone.Phone
FROM Contacts.Phone
WHERE Phone.ContactId = :contactId
ORDER BY 1 -- put e-mail addresses before phone-numbers
;
第一列将返回结果的“类型”,第二列将具有原点。
答案 2 :(得分:0)
如果您真的希望将结果分成两列,其中包含重复数据的NULL,那么如果MySQL支持其他某些DBMS系统允许的RANK() OVER (PARTITION BY ...
语法,那么这将非常有用。遗憾的是它没有,但Daniel Vassallo通过描述如何在this question中在MySQL中完成它来解决问题。
根据您的情况调整他的方法:
SELECT Phone.Phone,
CASE Email.Email
WHEN @curEmail THEN NULL
ELSE @curEmail := Email.Email END AS Email
FROM Contacts.Phone, Contacts.Email, (SELECT @curEmail := '') AS r
WHERE Phone.ContactId = :contactId AND Email.ContactId = :contactId
当我在你的问题中对测试数据运行时,我得到了:
Row 1: 555-555-5555 - email@email.com
Row 2: 666-666-6666 - NULL
这是期望的结果。