2011-09-19 98 views
2

我使用的數據庫目前確實有兩個表,一個拿着屬性「contact_person」。此屬性相比,它被命名爲「contact1」到「contact4」,確定從第二個表顯示什麼其他屬性在另一個表中的多個屬性(不是元組!)(即「EMAIL1」到「EMAIL4」)。所以第一個表只保存聯繫人,第二個表是幾個聯繫人的實際地址數據(再次,他們都在一行或一個元組中)。別告訴我,這AINT正確的數據庫設計 - 我有我得到了-.-選擇尚未在記錄的所有記錄

得到什麼我選擇執行選擇每個比較UNION他們正確的聯繫人數據的工作。這工作正常,執行查詢的應用程序足夠執行。它看起來很簡單,像這樣:現在

SELECT contact1, email1, phone1 FROM T1,T2 WHERE contact_person = contact1 
UNION ALL 
SELECT contact2, email2, phone2 FROM T1,T2 WHERE contact_person = contact2 
UNION ALL 
SELECT contact3, email3, phone3 FROM T1,T2 WHERE contact_person = contact3 
UNION ALL 
SELECT contact4, email4, phone4 FROM T1,T2 WHERE contact_person = contact4 

,由於畸形和非錯誤檢查INSERT查詢,有可能是「contact_person」是NULL或空字符串或任何「 contactN「屬性爲NULL。所以我需要另一個SELECT查詢,它顯示所有記錄在數據庫中但不在記錄集中的記錄

有了,可以使用類似於這樣可以實現給定的例子:

UNION 
SELECT contact_person, 'N/A', 'N/A' FROM T1,T2 

在現實生活中查詢我(需要)做了很多「contact_person」和「contactN」 S的格式,所以簡單地做一個UNION(沒有ALL,所以平等的記錄被排除)不會工作(contactN實際上是一個多字段值,格式不一致,所以最後一個查詢返回的記錄可能不同於上面的記錄,甚至對於數據庫中的相同條目)。此外,查詢是如此之大已經是它沒有選擇使用第一查詢相反,排除它的記錄,像這樣:

UNION ALL 
SELECT contact_person, 'N/A', 'N/A' FROM T1,T2 
    WHERE contact_person <> contact1 
    AND contact_person <> contact2 
    AND contact_person <> contact3 
    AND contact_person <> contact4 

所以有另一種方式來顯示那些沒有被選中的所有記錄與上面發佈的第一個查詢?也許通過某種方式運行一個子查詢(OFC確實存在返回記錄的UID - 我只是不知道如何在這種情況下使用它)?第一個查詢是否可以用更簡單的方式寫出來?

回答

2
;WITH cp AS 
(
    -- strongly recommend appropriate table prefixes in select list: 
    SELECT UID, contact1, email1, phone1 
    -- also strongly recommend proper inner joins: 
     FROM T1 INNER JOIN T2 ON t1.contact_person = t2.contact1 
    UNION ALL 
    SELECT UID, contact2, email2, phone2 
     FROM T1 INNER JOIN T2 ON t1.contact_person = t2.contact2 
    UNION ALL 
    SELECT UID, contact3, email3, phone3 
     FROM T1 INNER JOIN T2 ON t1.contact_person = t2.contact3 
    UNION ALL 
    SELECT UID, contact4, email4, phone4 
     FROM T1 INNER JOIN T2 ON t1.contact_person = t2.contact4 
) 
SELECT contact1, email1, phone1 FROM cp 
UNION ALL 
SELECT t1.contact_person, 'N/A', 'N/A' 
FROM T1 INNER JOIN T2 ON t1.contact_person = t2.contact1 
WHERE UID NOT IN (SELECT UID FROM cp); 

您可能還會考慮更規範化/關係設計?

+0

哦,我與表前綴工作,並加入 - 我只是試圖保持它短而簡單。此外,我不幸現在沒有重新設計數據庫的任何部分的選項。這隻有在訪問它的應用程序將被重寫時纔會發生,這是我目前工作的公司發現它具有必要的貨幣資源來執行此操作。我現在試圖說服他們很長一段時間。無論如何,這看起來很像我需要的東西 - 只是我今天無法測試它(它在我們公司的關閉時間)。我會檢查它並明天標記答案。謝謝。 –

1

或者你可以先正常化T2,然後離開加入吧:

WITH normalisedT2 AS (
    SELECT 
    contact = CASE x.n 
     WHEN 1 THEN T2.contact1 
     WHEN 2 THEN T2.contact2 
     WHEN 3 THEN T2.contact3 
     WHEN 4 THEN T2.contact4 
    END, 
    email = CASE x.n 
     WHEN 1 THEN T2.email1 
     WHEN 2 THEN T2.email2 
     WHEN 3 THEN T2.email3 
     WHEN 4 THEN T2.email4 
    END, 
    phone = CASE x.n 
     WHEN 1 THEN T2.phone1 
     WHEN 2 THEN T2.phone2 
     WHEN 3 THEN T2.phone3 
     WHEN 4 THEN T2.phone4 
    END 
    FROM T2 
    CROSS JOIN (
     SELECT 1 UNION ALL 
     SELECT 2 UNION ALL 
     SELECT 3 UNION ALL 
     SELECT 4 
    ) x (n) 
) 
SELECT 
    contact = T1.contact_person, 
    email = COALESCE(T2.email, 'N/A'), 
    phone = COALESCE(T2.phone, 'N/A') 
FROM T1 
    LEFT JOIN normalisedT2 T2 ON T1.contact_person = T2.contact 
+0

工程就像一個魅力。我已經實施了Aarons版本,但它很高興看到它以另一種方式解決。我沒有時間比較兩個版本的性能(只在一個小的測試數據庫上實現你的版本),我只是出於興趣和學習一點點。所以感謝和+1 –