2011-07-15 86 views
0

我有人,公司和員工。這些表中的每一個都有一個外鍵返回到我稱之爲締約方的表格,這些表格通過觸發器維持着同級記錄。締約方有0到N個site_locators,它本身是參考城市的參考站點。用其他的東西代替一系列的LEFT JOIN?

我正在構建一個視圖,它將返回收件人的全名和城市。代碼因此它是:

SELECT 
     surname 
    , rest_of_name 
    , 'Employee' AS party_type_code 
    , party_id 
    , cities.name AS city_name 
    FROM 
       employees 
    LEFT JOIN site_locators USING (party_id) 
    LEFT JOIN sites   USING (site_id) 
    LEFT JOIN cities  USING (city_id) 
UNION ALL 
    SELECT 
     surname 
    , NULL::text 
    , 'Company' AS party_type_code 
    , party_id 
    , cities.name AS city_name 
    FROM 
       companies 
    LEFT JOIN site_locators USING (party_id) 
    LEFT JOIN sites   USING (site_id) 
    LEFT JOIN cities  USING (city_id) 
UNION ALL 
    SELECT 
     surname 
    , rest_of_name 
    , 'Person' AS party_type_code 
    , party_id 
    , cities.name AS city_name 
    FROM 
       people 
    LEFT JOIN site_locators USING (party_id) 
    LEFT JOIN sites   USING (site_id) 
    LEFT JOIN cities  USING (city_id) 

我真的不喜歡每個聯盟的多個左聯接。我重構代碼作爲單獨的步驟做的連接只一次:

SELECT 
    parties.* 
    , cities.name AS city_name 
FROM (
    SELECT /* As above, minus city_name */ 
    FROM employees 
    UNION ALL 
    SELECT /* As above, minus city_name */ 
    FROM companies 
    UNION ALL 
    SELECT /* As above, minus city_name */ 
    FROM people 
) AS parties 
    LEFT JOIN site_locators USING (party_id) 
    LEFT JOIN sites   USING (site_id) 
    LEFT JOIN cities  USING (city_id) 

這第二個查詢速度更快,因爲所有的表被過濾後的連接只發生一次。我想知道的是,如果我可以進一步重構這樣的話,如果site_locators沒有爲一個派對返回行,那麼我甚至不需要搜索網站或城市?我想知道這是否可以用一些INNER JOINs而不是所有的LEFT JOIN來重寫。我之前對LEFT JOIN有過不好的體驗,並希望減少它們的數量。

注:黨表存在減少表的數量。如果它不存在,我需要每個派對類型和定位器類型的表格:employee_site_locators,people_site_locators,company_site_locators,employee_email_locators,people_email_locators等。通過締約方表,我可以爲每個定位器類型提供一個* _locator表。

+1

如果你需要你的行到* always *列出的所有表中都有數據,那麼將'LEFT JOIN'改爲'INNER JOIN'就可以實現這一點,並且也應該限制搜索的範圍。您應該(可能)能夠按原樣離開查詢,因爲大多數現代優化器都會混淆連接順序。 –

+0

我瞭解LEFT和INNER加入的區別。 city_name列中的數據是可選的:如果存在,我需要它。如果它不存在,那很好,因此我使用了LEFT JOIN。 –

+0

好的,對不起,這不是你的要求的一部分(或者至少,我沒有閱讀它)。在這種情況下,左邊的連接可能會成爲你最好的選擇;除非一些後續的連接可以用內部連接重寫。但是,如果不知道你的表格結構和期望的結果,那麼確切地判斷可以用這種方式改變的東西有點困難。 –

回答

0

首先,那第一個重構是非常好的。

其次,是的左連接約束策劃者。然而,將這些阻塞到具有外部聯接的內部聯接的塊中會以更多方式限制策劃者,並且這些都是更大的限制。總的來說,我看到規劃師在使用索引時不太能夠使用索引,因爲左連接按照您描述的方式進行分解。

總的來說,最好先把注意力放在清晰度上,然後再看看調整來執行更好的表現,而不是先擔心性能,然後再着眼於清晰度。有一件事會幫助,雖然取代USINGON.最後看看你的模型,看看什麼是一個左連接,什麼是內連接。注意這些是非常不同的,所以它們不能被直接替換。

+0

你相信'ON'比'USING'更清晰嗎? 'USING'減少了總字數,在我看來,這使得閱讀起來更容易。 「ON」如何提高清晰度? –