進行多個聯接時重複
我有 4 個 MySQL 表
1. companies - {id*, company} 2. employees - {id*, fname, lname, id_company*} 3. technologies - {id*, technology} 4. company_technologies - {id_technology*, id_company*}
如果欄位具有“*”,則對其進行索引。
公司可以使用多種技術並擁有多名員工。
我正在嘗試做的是編寫一個查詢,該查詢將選擇使用任何給定技術的所有員工及其公司。問題是當我嘗試做這樣的事情時我有重複:
SELECT employees.*, companies.* FROM companies LEFT JOIN employees on companies.id = employees.id_company LEFT JOIN company_technologies ON companies.id = company_technologies.id_company WHERE company_technologies.id_technology IN(1,2,3)
例如,如果一家公司正在使用技術 1 和 2 - 它將與所有人一起出現兩次。
如果我在最後添加“GROUP BY Companies.id”條件 - 每家公司只有一名員工,而我需要所有員工。
表 1、2 和 4 有幾百萬條記錄,所有表都是 InnoDB。
您可以使用或將 轉換
join
為半連接:IN``EXISTS
SELECT employees.*, companies.* FROM companies LEFT JOIN employees ON companies.id = employees.id_company WHERE EXISTS ( SELECT 1 FROM company_technologies WHERE companies.id = company_technologies.id_company AND company_technologies.id_technology IN (1,2,3) ) ;
另一種方法是在子查詢中使用
GROUP BY
orDISTINCT
然後加入:SELECT e.*, c.* FROM companies AS c LEFT JOIN employees AS e ON c.id = e.id_company JOIN ( SELECT id_company FROM company_technologies WHERE id_technology IN (1,2,3) GROUP BY id_company ) AS ct ON c.id = ct.id_company ;
一旦你有一個或多個查詢正常工作,你就可以開始擔心效率了。我會在聯結表上添加 2 個複合索引,一個
(id_technology,id_company)
和一個(id_company,id_technology)
(並刪除單個索引。)然後使用各種參數和表大小測試所有查詢,並檢查使用了哪些索引以及執行計劃是什麼。
因為您加入的是 company_technologies,所以您將在每場比賽中獲得一排。因為您沒有在 select 子句中包含 company_technologies 中的任何內容,所以看起來好像您得到了重複項
您要查找的是 where 子句中的子查詢,而不是 from 子句中的聯接。
WHERE employees.id_company IN (SELECT id_company FROM company_technologies WHERE id_technology IN (1,2,3))