2017-05-23 39 views
0

我在我的數據庫中有一張表,用於記錄用戶 有效或無效的時間。如果用戶從活動狀態切換到非活動狀態或反之亦然(或更改地址等任何其他屬性),則會添加新記錄。一個簡化的版本是這樣的:在MySQL中計算時間範圍內的條目

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); 

我的問題是,我不知道如何做到這一點的日期範圍(比如一月至三月)。有沒有辦法做到這一點?

示例數據庫和表

-- 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

你需要一個calendar_table有一個月的日期範圍,與dt_begindt_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 
    ; 

輸出

enter image description here

注:您可以使用LEFT JOIN如果想要個月0的活動。