来自多个表的SQL SELECT列而不重复数据

时间:2011-11-30 03:38:15

标签: mysql sql

我试图使用以下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。

3 个答案:

答案 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

这是期望的结果。