有人可以帮助我为活跃用户创建一个mysql月度报告。 用户在特定日期拜访医生。该日期记录在访问日期。然后他们会立即预约他们应该回来的约会日期。用户活跃的月份是从访问月份到预约日期月份加上90天宽限期的用户。如果他们不在约会日期,他们将获得90天的宽限期,其中他们'仍然会被视为活跃用户。之后他们不再被认为是活跃的。
Users Table
+------------+------------+------------+
| UserID | visit |Appointment |
+------------+------------+------------+
| 10001 | 01-01-2010 | 01-02-2010 |
| 10001 | 05-02-2010 | 01-03-2010 |
| 10002 | 20-07-2010 | 15-10-2010 |
| 10003 | 01-11-2010 | 10-11-2010|
+------------+------------+------------+
期望的结果将是
Monthly Report
+------------+------------+------------+
| Month | active | |
+------------+------------+------------+
| 2010-01 | 1 | |
| 2010-02 | 1 | |
| 2010-03 | 1 | |
| 2010-04 | 1 | |
| 2010-05 | 1 | |
| 2010-07 | 1 | |
| 2010-08 | 1 | |
| 2010-09 | 1 | |
| 2010-10 | 1 | |
| 2010-11 | 2 | |
| 2010-12 | 2 | |
| 2011-01 | 1 | |
+------------+------------+------------+
CREATE TABLE `visits` (
`id` int(10) NOT NULL,
`userid` int(10) NOT NULL,
`visit` date NOT NULL,
`appointment` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `visits` (`id`, `userid`, `visit`, `appointment`) VALUES
(1, 10001, '2010-01-01', '2010-02-01'),
(2, 10001, '2010-02-05', '2010-03-01'),
(3, 10002, '2010-07-20', '2010-10-15'),
(4, 10003, '2010-11-01', '2010-11-10');
ALTER TABLE `visits`
ADD PRIMARY KEY (`id`);
ALTER TABLE `visits`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10007;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
答案 0 :(得分:1)
对于那些可能需要这个的人。
SELECT
date_format(c.dt,'%Y-%m') AS "month",
c.dt AS date,
a.visit,
a.fu,
COUNT(DISTINCT userid) AS Active
FROM calendar_table c
LEFT JOIN visits v ON c.dt BETWEEN date_format(v.visit,'%Y-%m') AND
DATE_SUB(date_add(v.appointment, INTERVAL 90 day), INTERVAL
date_format((LAST_DAY(date_add(v.appointment, INTERVAL 90 day))),'%d')-1 DAY)
WHERE c.d = 1
AND c.y IN (2010,2011)
GROUP BY c.dt
答案 1 :(得分:0)
这种类型的要求通常需要某种形式的"计数表"和/或"日历表"。也就是说,对于你的专栏" month",你真的需要这是一个表格。这使您可以将日期范围表示为一组行(在这种情况下每月一个)。
如果您将日期范围表示为行,则在连接条件中使用“visits
之间的外部联接”。这将允许您计算每个时间单位有多少用户。
对于以下示例,我使用了this article on a calendar table
中的代码CREATE TABLE calendar_table (
dt DATE NOT NULL PRIMARY KEY,
y SMALLINT NULL,
q tinyint NULL,
m tinyint NULL,
d tinyint NULL,
dw tinyint NULL,
monthName VARCHAR(9) NULL,
dayName VARCHAR(9) NULL,
w tinyint NULL,
isWeekday BINARY(1) NULL,
isHoliday BINARY(1) NULL,
holidayDescr VARCHAR(32) NULL,
isPayday BINARY(1) NULL
);
CREATE TABLE ints ( i tinyint );
INSERT INTO ints VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
INSERT INTO calendar_table (dt)
SELECT DATE('2010-01-01') + INTERVAL a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i DAY
FROM ints a JOIN ints b JOIN ints c JOIN ints d JOIN ints e
WHERE (a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i) <= 11322
ORDER BY 1;
UPDATE calendar_table
SET isWeekday = CASE WHEN dayofweek(dt) IN (1,7) THEN 0 ELSE 1 END,
isHoliday = 0,
isPayday = 0,
y = YEAR(dt),
q = quarter(dt),
m = MONTH(dt),
d = dayofmonth(dt),
dw = dayofweek(dt),
monthname = monthname(dt),
dayname = dayname(dt),
w = week(dt),
holidayDescr = '';
现在,根据您的问题使用您的示例数据,使用以下查询:
select
date_format(c.dt,'%Y-%m') as "month"
, count(distinct userid) as active
from calendar_table c
left join visits v on c.dt between v.visit and date_add(v.appointment, INTERVAL 90 DAY)
where c.y in (2010,2011)
group by
date_format(c.dt,'%Y-%m')
请注意,此方法将为您提供24行(每月超过2年),因此您将获得更多的零行,而不是问题的预期结果。只需调整where子句以适合所需的日期范围。
请参阅此operating as an example at sqlfiddle
注意:此示例中没有注意索引或性能