Join

MySQL在同一個表上的多個連接問題

  • September 25, 2017

使用 MySQl 5.6 作為我的數據庫,我試圖在另一個連接的表上加入一個表兩次,但我得到了重複的結果,而不是合併的行。

所以,我有一個檢查表,可以將檢查分配給一個或多個儲存在 check_assigned_area 表中的區域。此表中的條目可以是位置或部門。位置是部門的父級。

所以,我通過 PK(check_id)將 checks_assigned_area 表加入到檢查表中

然後我嘗試加入區域表兩次,一次用於位置,一次用於部門,具體取決於 area_level。3是一個位置,4是一個部門。

但不是查詢返回帶有位置名稱和部門名稱的單行。它返回 2 個單獨的行,並且沒有填充部門名稱。

我嘗試了各種左/內/右連接組合、不同、分組方式,但我無法正確獲取數據。

我什至可以這樣做嗎?我的邏輯告訴我是的,但實際上我無法讓它工作。

如果我可以讓它輸出我需要的數據有什麼想法嗎?

這是我的數據和查詢的 SQL 小提琴http://sqlfiddle.com/#!9/63d6ce/4

檢查表:

+----------+---------------+------------+------------+--------+----------+
| check_id | check_type_id | 到期 | created_by | 狀態 | 簽收 |
+----------+---------------+------------+------------+--------+----------+
| 19335 | 43 | 18/09/2017 | 3 | 1 | 1 |
| 19336 | 4 | 19/09/2017 | 3 | 1 | 1 |
| 19358 | 62 | 21/09/2017 | 47336 | 1 | 1 |
+----------+---------------+------------+------------+--------+----------+

檢查分配區域表:

+------------------------+---------------+----------+
| check_assigned_area_id | check_area_id | check_id |
+------------------------+---------------+----------+
| 18801 | 9 | 19335 |
| 18802 | 816 | 19336 |
| 18803 | 816 | 19336 |
| 18804 | 8091 | 19358 |
| 18835 | 8092 | 19358 |
+------------------------+---------------+----------+

詢問:

SELECT `c`.*, `t`.`check_name`,`a`.`check_area_id`,`l`.`area_name` AS 'location_name', `d`.`area_name` AS 'dept_name'
FROM `checks` `c`
LEFT JOIN `check_assigned_areas` `a` ON `a`.`check_id` = `c`.`check_id`
LEFT JOIN `areas` `l` ON `l`.`area_id` = `a`.`check_area_id` AND `l`.`area_level` = '3'
LEFT JOIN `areas` `d` ON `d`.`area_id` = `a`.`check_area_id` AND `d`.`area_level` = '4'
LEFT JOIN `check_types` `t` ON `t`.`check_type_id` = `c`.`check_type_id`
WHERE `c`.`org_id` = '297'
AND `c`.`status` != '0'
AND `c`.`due` <= '2017-09-21'

我調整了你提供的小提琴,我相信我現在得到了你想要的結果。這是更新的小提琴

更新後的查詢是:

SELECT `c`.*, `t`.`check_name`,`al`.`check_area_id` as 'loc_check_area_id',`l`.`area_name` AS 'location_name',`ad`.`check_area_id` as 'dept_check_area_id', `d`.`area_name` AS 'dept_name'
FROM `checks` `c`
LEFT JOIN (`check_assigned_areas` `al` 
            INNER JOIN `areas` `l` ON `l`.`area_id` = `al`.`check_area_id` AND `l`.`area_level` = '3'
         ) ON `al`.`check_id` = `c`.`check_id`
LEFT JOIN (`check_assigned_areas` `ad` 
           INNER JOIN `areas` `d` ON `d`.`area_id` = `ad`.`check_area_id` AND `d`.`area_level` = '4'
         ) ON `ad`.`check_id` = `c`.`check_id`
LEFT JOIN `check_types` `t` ON `t`.`check_type_id` = `c`.`check_type_id`
WHERE `c`.`org_id` = '297'
AND `c`.`status` != '0'
AND `c`.`due` <= '2017-09-21'
;

這是結果(截斷以僅顯示位置和部門數據)。

check_id | ... | loc_check_area_id | location_name | dept_check_area_id |  dept_name
----------+ ... +-------------------+---------------+--------------------+--------------
  19358  | ... |       8091        |  Luton Office |        8092        | Development
  19357  | ... |      (null)       |     (null)    |       (null)       |   (null)

由於具有有效位置和部門的支票有兩個單獨check_assigned_areas的行,因此從邏輯上講,您將獲得該支票的兩行。一行代表一個位置,一個代表部門。因此,您為這些值獲得了單獨的行。

我更改了查詢,因此不是單獨LEFT JOIN的 s for check_assigned_areasareas即位置,areas即部門,而是一個LEFT JOINforcheck_assigned_areasareas,即位置,以及一個單獨LEFT JOIN的 forcheck_assigned_areasareas,即部門。在這兩個LEFT JOINs 中,check_assigned_areas那組areas行被INNER JOIN編輯在一起。

這意味著您將獲得與此檢查相關的位置的一(組)行,以及部門的一行。

請注意,其中涉及兩個check_assigned_areas.check_area_id值,因此我將check_area_idfrom the location 和check_area_idfrom the department 顯示為兩個單獨的列。

另請注意,如果有多個areas與支票相關的位置和/或多個部門,您將看到找到的位置和部門的每個可能組合對應的一行;這就是為什麼寫上一段是為了允許這樣。

但是,如果有 0 個或 1 個位置,以及 0 個或 1 個部門,您將得到一行,其中包含找到的位置和部門。

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