sql查询以获取日历中确实有事件的用户

rsl1atfo  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(272)

我有以下数据库表:
用户表:

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

有人能帮我完成吗?这在1sql查询中可能吗?

hgc7kmma

hgc7kmma1#

如果不进行硬编码,很难将列名生成为下一个日期的字符串(如“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 指后天等。
此外,此解决方案还提供了一个包含所有零的列(即没有任何事件的天数)

nbysray5

nbysray52#

实际上这里你需要左连接
这是因为您希望表“user”中的元素在表booking中没有链接。
使用left join将返回表user中的所有元素,不管它是否有预订,然后使用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中,它是另一种方式,只是混淆一切。。。

相关问题