日期范围内的Mysql频率
我有一个MySQL数据库:日期范围内的Mysql频率,mysql,sql,Mysql,Sql,我有一个MySQL数据库: Date Customer_ID 我怎样才能把它变成: Customer_ID | Count_Visits_Past_Week | Count_Visits_Past_Month | Count_Visits_Past_90days | Count_Total 注意:计数\u总计=其他三个计数的总和 谢谢我想这会给你想要的 select customer_id, sum(case when splitter = 'week' then n
Date Customer_ID
我怎样才能把它变成:
Customer_ID | Count_Visits_Past_Week | Count_Visits_Past_Month | Count_Visits_Past_90days | Count_Total
注意:计数\u总计=其他三个计数的总和
谢谢我想这会给你想要的
select customer_id,
sum(case when splitter = 'week' then num_visits else 0 end) as visits_this_week,
sum(case when splitter = 'month' then num_visits else 0 end) as visits_this_month,
sum(case when splitter = '90days' then num_visits else 0 end) as visits_last_90days,
sum(num_visits) as total
from (select customer_id, 'week' as splitter, count(*) as num_visits
from tbl
where extract(week from date) = extract(week from sysdate())
and extract(year from date) = extract(year from sysdate())
group by customer_id
union all
select customer_id, 'month' as splitter, count(*) as num_visits
from tbl
where extract(month from date) = extract(month from sysdate())
and extract(year from date) = extract(year from sysdate())
group by customer_id
union all
select customer_id, '90days' as splitter, count(*) as num_visits
from tbl
where date between date_sub(sysdate(), interval 90 day) and
sysdate()) x
group by customer_id
sql FIDLE示例:第一步是确定指定日期范围的分界点 这里有几个问题需要回答:您是否只想比较日期('yyyy-mm-dd')而忽略任何时间组件 所谓“过去一周”,是指过去七天内,还是指自上一个星期日至今,还是指从星期日到星期六的最后一整周 “上个月”是指上一个月,从第一个月到月底?或者,这是否意味着如果查询是在本月20日运行的,那么我们需要上个月20日到今天的日期?还是昨天 一旦我们知道相对于今天的日期开始和结束每个指定时段的时间点,我们就可以构建计算这些日期的表达式 例如,“过去的一周”可以表示为最近的七天期间:
DATE(NOW())-INTERVAL 1 WEEK -thru- DATE(NOW())
“过去一个月”可以表示为直到今天的前一个月的同一个“月日”(如17日):
DATE(NOW())-INTERVAL 1 MONTH -thru- DATE(NOW())
这实际上是第一步,确定每个指定时段的开始和结束日期
一旦我们有了它,我们就可以继续构建一个查询,该查询将获得每个时段内
date
列的行数
“技巧”是在查询的SELECT列表中的表达式中使用条件测试。如果该行要包含在“计数”中,我们将使用这些条件测试返回1,如果该行被排除,则返回0或NULL
我更喜欢使用SUM()
aggregate函数来获取“count”。但是也可以使用COUNT()
aggregate。(如果我们使用COUNT()
,我们需要使用一个表达式,该表达式在要排除行时返回NULL。我更喜欢返回1或0;我认为这使调试更容易
下面是“count”查询的大致情况
SELECT t.Customer_Id
, SUM(IF( <some_condition> ,1,0) AS Count_something
, SUM(IF( <other_condition> ,1,0) AS Count_something_else
FROM mytable t
GROUP BY t.Customer_Id
该查询不返回“count”,它只返回表达式的结果,这在测试中很有用。当然,我们要测试返回每个期间的开始和结束日期的表达式:
SELECT DATE(NOW()) - INTERVAL 1 WEEK AS past_week_begin
, DATE(NOW()) AS past_week_end
使用这种方法,同一行可以通过一次查询和一次表传递包含在多个“计数”中 请注意,下面查询中的
SUM()
聚合中的表达式利用了一种方便的速记方式,作为布尔值计算的表达式将返回1(如果为真)、0(如果为假)或NULL
要使用计数聚合,我们需要确保被聚合的表达式在要“计数”行时返回非NULL,在将该行从计数中排除时返回NULL。因此,如果表达式返回的值为零,我们使用方便的NULLIF函数返回NULL
SELECT t.Customer_ID
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 WEEK AND DATE(NOW()),0))
AS Count_Visits_Past_Week
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 MONTH AND DATE(NOW()),0))
AS Count_Visits_Past_Month
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 90 DAY AND DATE(NOW()),0))
AS Count_Visits_Past_90days
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 WEEK AND DATE(NOW()),0))
+ COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 MONTH AND DATE(NOW()),0))
+ COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 90 DAY AND DATE(NOW()),0))
AS Count_Total
FROM mytable t
GROUP BY t.Customer_Id
注意:NULLIF(a,b)
是的一个方便的缩写,如果a为NULL,则返回b,否则返回a
返回Count\u Total有点奇怪,因为它有可能多次“计数”同一行……但是它返回的值应该与单个计数的总和相匹配。当你说“过去的一周”和“过去的一个月”时,你是指与当前周相同的一周,与当前月相同的一周吗?
SELECT t.Customer_ID
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 WEEK AND DATE(NOW()),0))
AS Count_Visits_Past_Week
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 MONTH AND DATE(NOW()),0))
AS Count_Visits_Past_Month
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 90 DAY AND DATE(NOW()),0))
AS Count_Visits_Past_90days
, COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 WEEK AND DATE(NOW()),0))
+ COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 1 MONTH AND DATE(NOW()),0))
+ COUNT(NULLIF( t.date BETWEEN DATE(NOW())-INTERVAL 90 DAY AND DATE(NOW()),0))
AS Count_Total
FROM mytable t
GROUP BY t.Customer_Id