1

我遇到了一个问题,经过多次失败的尝试后我似乎无法弄清楚。

我有三个表需要加入一些报告,并且在第三个表中可能不存在记录。但是如果第三张表中的记录不存在,我需要将第三张表的数据报一个空值,并获取所有符合其他条件的记录。

剥离到相关列,这里是表结构:

members -此表包含注册到网站的所有成员

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

任何人?

提前致谢!

4

3 回答 3

3

要从member表中获取所有结果,您需要到left join其他表并group by为该member表添加。

样本

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-24T05:18:17.320 回答
2

(假设您查询中的日期范围应在 2013 年 8 月而不是 2013 年 7 月之间)。您需要将针对购买的联接切换为外部联接。这将包括没有任何购买的成员,所以......

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

SQL小提琴

于 2013-08-24T05:18:06.403 回答
0

(用左连接替换内连接,你会得到正确的结果)

dbmembers m 左连接dbregistration_steps rmmemberId= rmemberId 左加入dbpurchases pmmemberId= pmemberId

或者您可以用左连接单独替换任何购买。

注意:左连接和左外连接都产生相同的结果,因此您可以使用其中任何一个。

于 2013-08-24T05:42:29.867 回答