我有人,公司和員工。這些表中的每一個都有一個外鍵返回到我稱之爲締約方的表格,這些表格通過觸發器維持着同級記錄。締約方有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表。
如果你需要你的行到* always *列出的所有表中都有數據,那麼將'LEFT JOIN'改爲'INNER JOIN'就可以實現這一點,並且也應該限制搜索的範圍。您應該(可能)能夠按原樣離開查詢,因爲大多數現代優化器都會混淆連接順序。 –
我瞭解LEFT和INNER加入的區別。 city_name列中的數據是可選的:如果存在,我需要它。如果它不存在,那很好,因此我使用了LEFT JOIN。 –
好的,對不起,這不是你的要求的一部分(或者至少,我沒有閱讀它)。在這種情況下,左邊的連接可能會成爲你最好的選擇;除非一些後續的連接可以用內部連接重寫。但是,如果不知道你的表格結構和期望的結果,那麼確切地判斷可以用這種方式改變的東西有點困難。 –