2011-11-30 175 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