我有以下数据库表:
用户表:
| id | name |
| 1 | bob |
| 2 | jane |
| 3 | tim |
| 4 | rex |
事件表:
| id | user_id | date |
| 1 | 1 | 12/05/2018 |
| 2 | 1 | 13/05/2018 |
| 2 | 2 | 15/05/2018 |
| 3 | 2 | 16/05/2018 |
| 4 | 3 | 27/05/2018 |
我想构建一个SQL查询,该查询检索在接下来的7天内确实发生任何事件的所有用户,并且还返回7天中的每一天的一列,其中包含该用户为每一天预订的事件数那些日子。
理想情况下,这就是我想要实现的目标:
| user_id | 12/05/2018 | 13/11/2018 | 14/11/2018 | 15/11/2018 |
| 1 | 1 | 1 | 0 | 0 |
| 2 | 0 | 0 | 0 | 1 |
到目前为止,我已经将此作为起点,但由于返回零行而无法正常工作
SELECT
users.id,
name
FROM
`users`
inner join bookings on `users`.`id` = bookings.teacher_id
WHERE
bookings.`date` BETWEEN NOW() AND DATE_ADD( NOW(), INTERVAL 7 DAY )
有人可以帮我实现这一目标吗?甚至可以在1个SQL查询中实现吗?
答案 0 :(得分:0)
实际上,您需要LEFT JOIN
之所以如此,是因为您希望表'user'中的元素在表预订中没有链接。
使用LEFT JOIN将返回表用户中的所有元素(无论它是否有预订),然后使用WHERE条件过滤并仅保留那些没有预订的用户(booking.id为NULL)
SELECT
u.id AS userId,
u.name AS userName
FROM
`user` AS u
LEFT JOIN booking AS b ON (
u.id = b.userId
AND b.`date` BETWEEN NOW() AND DATE_ADD( NOW(), INTERVAL 7 DAY )
)
WHERE
ISNULL(b.id)
在sql约定中,表名采用单数形式...在nosql中,这是另一种方式,只是为了混淆一切...
答案 1 :(得分:0)
在不进行硬编码的情况下,很难将列名生成为下一个日期的字符串(例如'2018-11-01','2018-11-02')。
但是我可以给出一个答案,其中列名被命名为d1..d7
。希望你的情况很好。这可能不是最佳解决方案,但可以。
SELECT
tt.user_id,
SUM(tt.d1) AS d1,
SUM(tt.d2) AS d2,
SUM(tt.d3) AS d3,
SUM(tt.d4) AS d4,
SUM(tt.d5) AS d5,
SUM(tt.d6) AS d6,
SUM(tt.d7) AS d7
FROM
(SELECT
t.user_id,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 1 DAY)) THEN t.total ELSE 0
END) AS d1,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 2 DAY)) THEN t.total ELSE 0
END) AS d2,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 3 DAY)) THEN t.total ELSE 0
END) AS d3,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 4 DAY)) THEN t.total ELSE 0
END) AS d4,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 5 DAY)) THEN t.total ELSE 0
END) AS d5,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 6 DAY)) THEN t.total ELSE 0
END) AS d6,
(CASE WHEN t.`date` = DATE(DATE_ADD(NOW(), INTERVAL 7 DAY)) THEN t.total ELSE 0
END) AS d7
FROM
(
SELECT b.user_id, b.`date`, COUNT(*) as total
FROM `bookings` b
WHERE b.`date` BETWEEN NOW() AND DATE_ADD( NOW(), INTERVAL 7 DAY )
GROUP BY b.user_id, b.`date`) t
) tt
GROUP BY tt.user_id
此查询为您提供的表给我这样的结果。
| user_id | d1 | d2 | d3 | d4 | d5 | d6 | d7 |
----------------------------------------------
| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| 3 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
第二天d1
的意思是。 d2
表示后天,等等。
此解决方案还为列也提供了全零(即没有任何事件的天数)