2011-11-30 128 views
3

我试图用下面的sql语句来查询2个表,试图从每个包含特定id的表中返回所有记录。从多个表中重复SQL SELECT列而不重复数据

SELECT Phone.Phone, Email.Email FROM Contacts.Phone, Contacts.Email 
WHERE Phone.ContactId = :contactId AND Email.ContactId = :contactId 

Contacts.Phone表包含2个指定编号的电话号码和Contacts.Email包含给定ID 1个电子邮件。使用上面的sql查询,我得到以下行返回。当然,这仅仅是一个例子,其中每个表的结果集在行数上匹配。

Row 1: 555-555-5555 - [email protected] 
Row 2: 666-666-6666 - [email protected] 

电子邮件被重复,以填补在第二排,当我试图让:

Row 1: 555-555-5555 - [email protected] 
Row 2: 666-666-6666 - NULL 

我想我需要使用UNION以某种方式加入表,但我可以不知道如何编写sql语句。另一个选择是执行2个单独的SQL查询,这将更容易,但我认为性能明智的做法是在一个查询中收集所需的所有数据。

我正在使用MySQL。

+0

我想你需要'LEFT JOIN'电子邮件表。 – favoretti

+0

@ryandlf您有一个联系人ID有2个(或更多)电话号码,并且可以有一个联系人ID有2个(或更多)电子邮件? – Nalaka526

+0

我想你会想要使用两个子查询,每个都有一些ROWNUM/rank/row_number变体,并在该字段上执行完整的外连接。对于一个特定的查询,你必须告诉我们你正在使用的是什么RDBMS(MySQL?Oracle?SQL Server?PostgreSQL?其他?)。这就是说,我认为你的陈述“表现明智,最好是在一个查询中收集我需要的所有数据”是错误的。一个拉* n *行的查询优于每个拉一行的* n *查询,但没有理由将两个逻辑分离的查询合并为一个。 – ruakh

回答

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 
; 

第一列将返回结果的“类型”,第二列将基准。

+0

谢谢。对我而言,这种方法实际上比返回空值效果更好,因为我可以检查第一列并相应地放置数据。就我所知,订单按表1顺序排列,是正确的吗?是否有特定的理由首先返回电子邮件数据? – ryandlf

+0

@ryandlf:不客气。 'ORDER BY 1'实际上是指“按第一个字段排序”(在这种情况下是“类型”字段)。首先发送电子邮件的唯一原因是,我认为在“PHONE”之前将所有电子邮件和所有其他电子邮件以及“EMAIL”排序会更好。如果你想要电话号码,你可以做'ORDER BY 1 DESC'。如果你根本不关心订单 - 如果你是O.K.可能会收到(比如说)一些电子邮件地址,然后是一些电话号码,然后是更多的电子邮件地址 - 那么您可以完全放弃'ORDER BY 1'。 – ruakh

0

如果您真的想要将结果放在两列用NULL表示重复数据,那么如果MySQL支持其他一些DBMS系统允许的RANK() OVER (PARTITION BY ...语法,这将非常有帮助。遗憾的是,事实并非如此,但Daniel Vassallo通过描述如何在MySQL中完成this question来拯救。

适应他的做法给您的情况:

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 protected] 
Row 2: 666-666-6666 - NULL 

这是期望的结果。

2

使用left outer join解决您的问题,查询看起来sonething这样如果你使用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 protected] 
Row 2: 666-666-6666 - NULL