Mysql

進行多個聯接時重複

  • March 3, 2016

我有 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 BYorDISTINCT然後加入:

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))

引用自:https://dba.stackexchange.com/questions/53818