2016-04-28 46 views
1

我可以通过查询来获得每月和每家商店18至24岁的顾客数量。 我在做这样的:如何计算PostgreSQL在多个日期范围内的出现次数

select year, month, shop_id, count(birthday) 
from customers 
where birthday 
BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00' 
group by year, month, shop_id; 

现在,我有一个问题,使这个查询在同一时间几个范围。

我目前这个数据库模式:

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 

在第一个查询,其中一个店有它不管理的情况下没有客户。如果没有,如何获得0?

如何同时查询多个日期范围?

+0

在选择列表中有一个表达式,每个年龄组都有一个表达式。例如。 ',计数(当......然后1结束的情况下)为18_age_25,计数(当...的时候为 – jarlh

+0

年龄? –

回答

0

相反的过滤器,使用case语句:

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

非常感谢!简单高效。 – KillianKemps

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,而不是yearmonth。我认为这更灵活,但如果你愿意,应该很容易改变。

编辑:我意识到自己的yearmonth不是生日有关,但别的东西,我想访问日期?所以我更新了我的查询。如果您一次只检查一个月,则可以删除generate_series,并将年份和月份整数直接放入连接条件中。

相关问题