【问题标题】:Count non-matching rows as zero - how to? [duplicate]将不匹配的行数为零 - 如何? [复制]
【发布时间】:2018-01-19 18:44:25
【问题描述】:

我想做的是:

根据提供的入住和退房日期获取房间可用性计数。

这是表格:

categories

id | name
1  | Luxe
2  | Deluxe

reservations

id | category_id |  checkin    | checkout

1  |     1       | 2018-01-06  | 2018-01-10
1  |     2       | 2018-01-11  | 2018-01-13
3  |     2       | 2018-01-13  | 2018-01-17

预期输出

由于category_id = 2 的可用范围从2018-01-062018-01-10(参见reservations 表中的第一行),因此我在获取总计数时尝试将其可用性计数包括在内。

所以当运行这个查询时

SELECT 
    categories.name AS category,
    COUNT(reservations.id) AS free_count

FROM reservations 

INNER JOIN categories ON categories.id = reservations.category_id

WHERE checkin BETWEEN '2018-01-06' AND '2018-01-10'

GROUP BY categories.name, reservations.id

输出是:

category | free_count

Luxe     |   1

但是我愿意输出是:

category | free_count

Luxe     |   1
Deluxe   |   0

即将不匹配的行替换为零。如何做到这一点?非常鼓励使用没有嵌套查询的解决方案(由于它们的性能缓慢)。

【问题讨论】:

  • 将您的查询包装到某个table x,对类别表进行左连接。
  • @Krishna 你能解释一下包装的意义吗?这只是创建了一个别名,不是吗?
  • 是的,因为你已经在这个表中得到了你已经计算过的非零结果,如果你对类别表进行左连接,你将在不匹配的行上得到 0。

标签: mysql sql


【解决方案1】:

使用LEFT JOIN 而不是INNER JOIN

SELECT 
    c.name AS category,
    COUNT(r.id) AS free_count
FROM categories c
LEFT JOIN reservations r 
       ON c.id = r.category_id
      AND checkin BETWEEN '2018-01-06' AND '2018-01-10'
GROUP BY c.name

checkin 过滤器保持在ON 条件下很重要。当您在Where 子句中保留正确的表过滤器时,不匹配的记录将具有NULL 值,由于where 条件将在结果中过滤(基本上Left join 将转换为Inner join

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多