簡體   English   中英

MySQL INNER / LEFT JOIN在3個表上,其中第3個表中的記錄可能不存在

[英]MySQL INNER/LEFT JOIN on 3 tables, where records in 3rd table might not exist

我有一個問題,在一堆失敗的嘗試后我似乎無法弄清楚。

我有三個表需要為一些報告進行連接,而在第三個表中可能不存在記錄。 但是如果第3個表中的記錄不存在,我需要為來自第3個表的數據報告空值並獲取與其他條件匹配的所有記錄。

剝離到相關列,這里是表結構:

成員 - 此表包含注冊到網站的所有成員

| memberId  | insertDate          |
| ==========|=====================|
| 1         | 2013-08-01 18:18:16 |
| 2         | 2013-08-02 18:18:16 |
| 3         | 2013-08-03 18:18:16 |
| 4         | 2013-08-04 18:18:16 |
| 5         | 2013-08-05 18:18:16 |

registration_steps - 此表保存注冊過程的進度以及注冊是否已完成

| memberId  | completed |
| ==========|===========|
| 1         | 1         |
| 2         | 1         |
| 3         | 1         |
| 4         | 0         |
| 5         | 1         |

購買 - 此表持有,以及...購買

| memberId  | insertDate          |
| ==========|=====================|
| 1         | 2013-08-02 18:18:16 |
| 1         | 2013-08-03 17:18:16 |
| 1         | 2013-08-03 18:18:16 |
| 5         | 2013-08-07 18:18:16 |

這是我到目前為止提出的查詢:

SELECT `m`.`memberId`,
       DATE(`m`.`insertDate`) AS `regDate`,
       COUNT(`p`.`memberId`) AS `totalTransactions`,
       DATE(MIN(`p`.`insertDate`)) AS `firstPurchaseDate`,
       DATE(MAX(`p`.`insertDate`)) AS `latestPurchaseDate`,
       DATEDIFF(DATE(MIN(`p`.`insertDate`)), DATE(`m`.`insertDate`)) AS `daysBetweenRegAndFirstPurchase`
  FROM `db`.`members` `m`
       INNER JOIN `db`.`registration_steps` `r` ON `m`.`memberId` = `r`.`memberId` 
       INNER JOIN `db`.`purchases` `p` ON `m`.`memberId` = `p`.`memberId`
 WHERE `m`.`insertDate` BETWEEN '2013-07-01 00:00:00' AND '2013-07-31 23:59:59'
   AND `r`.`completed` = 1
GROUP BY `m`.`memberId`
;

它向我展示了我想要的一切,但是在桌面購買中缺少記錄的成員。

這是我得到的:

| memberId  | regDate             | totalTransactions | firstPurchaseDate   | latestPurchaseDate  | daysBetweenRegAndFirstPurchase |
| ==========|=====================|===================|=====================|=====================|================================|
| 1         | 2013-08-01 18:18:16 | 3                 | 2013-08-02 18:18:16 | 2013-08-03 18:18:16 | 1                              |
| 5         | 2013-08-05 18:18:16 | 1                 | 2013-08-07 18:18:16 | 2013-08-07 18:18:16 | 2                              |

但我需要的是:

| memberId  | regDate             | totalTransactions | firstPurchaseDate   | latestPurchaseDate  | daysBetweenRegAndFirstPurchase |
| ==========|=====================|===================|=====================|=====================|================================|
| 1         | 2013-08-01 18:18:16 | 3                 | 2013-08-02 18:18:16 | 2013-08-03 18:18:16 | 1                              |
| 2         | 2013-08-02 18:18:16 | 0                 | NULL                | NULL                | -1                             |
| 3         | 2013-08-03 18:18:16 | 0                 | NULL                | NULL                | -1                             |
| 5         | 2013-08-05 18:18:16 | 1                 | 2013-08-07 18:18:16 | 2013-08-07 18:18:16 | 2                              |

為了實現這一點,我嘗試將第二個內連接更改為左連接,左外連接並將where條件放入第一個內連接條件。 但是,我無法獲得理想的結果。 (必須承認我中斷了一些非常長時間運行的查詢,這些查詢可能是正確的(?)(實際場景中成員的總計數約為20k)。)

任何人?

提前致謝!

為了讓從所有的結果member需要表left join其它表,並添加group bymember表。

樣品

FROM `db`.`members` `m`
       LEFT OUTER JOIN `db`.`registration_steps` `r` ON `m`.`memberId` = `r`.`memberId` 
       LEFT OUTER JOIN `db`.`purchases` `p` ON `m`.`memberId` = `p`.`memberId`

左[外]

指定左表中不滿足連接條件的所有行都包含在結果集中,並且除了內連接返回的所有行之外,另一個表中的輸出列都設置為NULL。

(假設查詢中的日期范圍應介於2013-08而非2013-07之間)。 您需要將聯接與購買切換為外部聯接。 這包括沒有任何購買的會員......

   left outer JOIN `purchases` `p` ON `m`.`memberId` = `p`.`memberId`

SQL小提琴

(用左連接替換內連接,您將得到正確的結果)

來自db members m左加入db registration_steps r ON m memberId = r memberId離開加入db purchases p ON m memberId = p memberId

或者您可以使用左連接單獨替換任何購買。

注意:左連接和左外連接都產生相同的結果,因此您可以使用其中任何一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM