我的数据库中有一个表格,用于记录用户的持续时间 是活动的还是非活动的如果用户从活动切换到非活动或 反之亦然(或更改地址等任何其他属性)添加新记录。简化版本如下所示:
UserID state state_from state_to
1 active 2016-12-14 2017-01-15
2 active 2016-12-14 2017-02-02
3 active 2017-01-01 NULL
1 inactive 2017-01-16 2017-03-05
2 inactive 2017-02-02 NULL
1 active 2017-03-06 NULL
我想计算每月有多少用户在某个时候状态“活跃”。 1月到3月所需的输出表将是:
date user_count
2017-01 3
2017-02 2
2017-03 2
对于特定时间戳(例如2017年1月),我使用以下查询。
SET @stamp = '2017-01';
SELECT @stamp AS date, COUNT(UserID) AS user_count
FROM se_user
WHERE (state LIKE 'active' AND @stamp BETWEEN DATE_FORMAT(state_from,'%Y-%m') AND DATE_FORMAT(state_to,'%Y-%m') )
OR (state LIKE 'active' AND DATE_FORMAT(state_from,'%Y-%m') <= @stamp AND DATE_FORMAT(state_to,'%Y-%m') IS NULL);
我的问题是,我不知道如何在日期范围内(例如从1月到3月)这样做。有没有办法做到这一点?
示例数据库和表格
-- Set up a test database
DROP DATABASE IF EXISTS se_toy_example;
CREATE DATABASE se_toy_example;
USE se_toy_example;
-- Create example table
DROP TABLE IF EXISTS se_user;
CREATE TABLE se_user (
UserID INT(10),
state VARCHAR(10),
state_from DATE,
state_to DATE
);
-- Populate table
INSERT INTO se_user (UserID,state,state_from,state_to)
VALUES (1,'active','2016-12-14','2017-01-15'),
(2,'active','2016-12-14','2017-02-02'),
(3,'active','2017-01-01',NULL),
(1,'inactive','2017-01-16','2017-03-05'),
(2,'inactive','2017-02-02',NULL),
(1,'active','2017-03-06',NULL);
答案 0 :(得分:1)
您需要calendar_table
来获取月份日期范围,每个月都有dt_begin
和dt_end
。
因此,您对当前年度的查询将成为。
<强> SQL DEMO 强>
SELECT c.dt_begin, count(*)
FROM calendar_table c
JOIN se_user u
ON c.dt_begin <= COALESCE(u.state_to, curdate() )
AND c.dt_end >= u.state_from
WHERE dt_begin >= '2017-01-01'
AND dt_begin <= '2017-12-01'
AND state = 'active'
GROUP BY c.dt_begin
;
<强>输出强>
注意:如果想要0活动的月份,您可以使用LEFT JOIN
。