我能够进行查询,以获得每月和每个商店18至24岁的顾客数量。 我是这样做的:
shop_id | birthday | year | month |
--------+----------+------+--------
567 | 1998-10-10 | 2014 | 10 |
567 | 1996-10-10 | 2014 | 10 |
567 | 1985-10-10 | 2014 | 10 |
234 | 1990-10-10 | 2014 | 10 |
123 | 1970-01-10 | 2014 | 10 |
123 | 1974-01-10 | 2014 | 11 |
现在,我在同时对多个范围进行此查询时遇到问题。
我目前有这个数据库架构:
shop_id | year | month | 18 < age < 25 | 26 < age < 35
--------+------+-------+---------------+-------------
567 | 2014 | 10 | 2 | 1
234 | 2014 | 10 | 1 | 0
123 | 2014 | 10 | 0 | 0
我想得到这样的东西:
{{1}}
在第一个查询中,它不管理一个商店没有客户的情况。如果没有,怎么得到0?
如何同时查询多个日期范围?
答案 0 :(得分:0)
使用案例陈述代替过滤器:
select year, month, shop_id,
count(case when birthday between <range1> then 1 end) RANGE1,
count(case when birthday between <range2> then 1 end) RANGE2,
count(case when birthday between <range3> then 1 end) RANGE3
from customers
group by year, month, shop_id;
答案 1 :(得分:0)
“没有带零的行”是GROUP BY
查询的常见问题。解决方案是让您的FROM
成为具有完整列表的任何表,然后执行LEFT JOIN
。由于您按年份和月份进行分组,因此您需要生成完整的年份和月份列表。您可以使用generate_series
:
SELECT t.t, s.id, COUNT(c.birthday)
FROM shops s
CROSS JOIN generate_series('2014-01-01 00:00:00', '2015-01-01 00:00:00', interval '1 month') t(t)
LEFT OUTER JOIN customers c
ON c.shop_id = s.id
AND c.birthday
BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00'
AND c.year = EXTRACT(YEAR FROM t.t)
AND c.month = EXTRACT(MONTH FROM t.t)
GROUP BY t.t, s.id
ORDER BY s.id, t.t;
要获得两个日期范围的计数,您可以执行@ mo2建议的操作,或者您可以两次加入customers
表:
SELECT t.t, s.id, COUNT(DISTINCT c1.id), COUNT(DISTINCT c2.id)
FROM shops s
CROSS JOIN generate_series('2014-01-01 00:00:00', '2015-01-01 00:00:00', interval '1 month') t(t)
LEFT OUTER JOIN customers c1
ON c1.shop_id = s.id
AND c1.birthday
BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00'
AND c1.year = EXTRACT(YEAR FROM t.t)
AND c1.month = EXTRACT(MONTH FROM t.t)
LEFT OUTER JOIN customers c2
ON c2.shop_id = s.id
AND c2.birthday
BETWEEN '1982-01-01 00:00:00' AND '1992-01-01 00:00:00'
AND c2.year = EXTRACT(YEAR FROM t.t)
AND c2.month = EXTRACT(MONTH FROM t.t)
GROUP BY t.t, s.id
ORDER BY s.id, t.t;
请注意,在这两个查询中,我SELECT
使用完整的日期时间而不是year
和month
。我认为这更灵活,但如果你愿意,它应该很容易改变。
编辑:我意识到您的year
和month
与生日无关,但其他内容,我想是访问日期?所以我更新了我的查询。如果您一次只检查一个月,则可以删除generate_series
并将年份和月份整数直接放入连接条件。