我有一个用户表,当他们签名时和last_seen:
+--------+-----------+-----------+
| userid | signed_up | last_seen |
+--------+-----------+-----------+
| 1 | 1/1/14 | 1/3/14 |
| 2 | 1/1/14 | 1/5/14 |
| 3 | 1/3/14 | 1/5/14 |
| 4 | 1/6/14 | 1/7/14 |
+--------+-----------+-----------+
让我们假设每个用户每天都会在signed_up和last_seen之间访问该网站。我想计算每天有多少用户。我正在寻找的结果如下:
+--------+----------------+
| date | count_of_users |
+--------+----------------+
| 1/1/14 | 2 |
| 1/2/14 | 2 |
| 1/3/14 | 3 |
| 1/4/14 | 2 |
| 1/5/14 | 2 |
| 1/6/14 | 1 |
| 1/7/14 | 1 |
+--------+----------------+
只是为了澄清,这里是如何计算数字的(我不需要这张表,这只是一个例子)
+--------+----------------+-------+-------+-------+-------+
| date | count_of_users | user1 | user2 | user3 | user4 |
+--------+----------------+-------+-------+-------+-------+
| 1/1/14 | 2 | 1 | 1 | | |
| 1/2/14 | 2 | 1 | 1 | | |
| 1/3/14 | 3 | 1 | 1 | 1 | |
| 1/4/14 | 2 | | 1 | 1 | |
| 1/5/14 | 2 | | 1 | 1 | |
| 1/6/14 | 1 | | | | 1 |
| 1/7/14 | 1 | | | | 1 |
+--------+----------------+-------+-------+-------+-------+
不确定这是否超出了在MySql中应该做的事情...感谢您的帮助!
答案 0 :(得分:1)
mysql> CREATE TABLE IF NOT EXISTS calendar (date DATE NOT NULL PRIMARY KEY);
mysql> INSERT INTO calendar (SELECT calendar.date
FROM (
SELECT (SELECT MIN(signed_up) FROM users)
+ INTERVAL (a.val + (10 * b.val)) DAY
as date
FROM (select 0 as val union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all select 6
union all select 7 union all select 8 union all select 9)
as a
CROSS JOIN (select 0 as val union all select 1 union all select 2
union all select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all select 9)
as b
) calendar
WHERE calendar.date BETWEEN
(SELECT MIN(signed_up) FROM users) AND
(SELECT MAX(last_seen) FROM users));
mysql> select * from calendar;
+------------+
| date |
+------------+
| 2014-01-01 |
| 2014-01-02 |
| 2014-01-03 |
| 2014-01-04 |
| 2014-01-05 |
| 2014-01-06 |
| 2014-01-07 |
+------------+
7 rows in set (0.00 sec)
mysql> select * from users;
+--------+------------+------------+
| userid | signed_up | last_seen |
+--------+------------+------------+
| 1 | 2014-01-01 | 2014-01-03 |
| 2 | 2014-01-01 | 2014-01-05 |
| 3 | 2014-01-03 | 2014-01-05 |
| 4 | 2014-01-06 | 2014-01-07 |
+--------+------------+------------+
4 rows in set (0.00 sec)
获得日期范围表后,您要查找的查询可以表示为JOIN / GROUP BY操作:
mysql> SELECT c.date, count(c.date)
FROM calendar c JOIN users u WHERE c.date BETWEEN u.signed_up AND u.last_seen
GROUP BY c.date;
+------------+---------------+
| date | count(c.date) |
+------------+---------------+
| 2014-01-01 | 2 |
| 2014-01-02 | 2 |
| 2014-01-03 | 3 |
| 2014-01-04 | 2 |
| 2014-01-05 | 2 |
| 2014-01-06 | 1 |
| 2014-01-07 | 1 |
+------------+---------------+
7 rows in set (0.00 sec)
如果您经常进行此类查询,则需要生成(并保留)日历表。但是,如果您不想创建日历表,则可以使用单个查询动态生成结果:
mysql> SELECT c.date, COUNT(c.date)
FROM (SELECT calendar.date
FROM (
SELECT (SELECT MIN(signed_up) FROM users)
+ INTERVAL (a.val + (10 * b.val)) DAY
as date
FROM (select 0 as val union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all select 6
union all select 7 union all select 8 union all select 9)
as a
CROSS JOIN (select 0 as val union all select 1 union all select 2
union all select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all select 9)
as b
) calendar
WHERE calendar.date BETWEEN
(SELECT MIN(signed_up) FROM users) AND
(SELECT MAX(last_seen) FROM users)) c
JOIN users u WHERE c.date BETWEEN u.signed_up AND u.last_seen
GROUP BY c.date
产生
+------------+---------------+
| date | COUNT(c.date) |
+------------+---------------+
| 2014-01-01 | 2 |
| 2014-01-02 | 2 |
| 2014-01-03 | 3 |
| 2014-01-04 | 2 |
| 2014-01-05 | 2 |
| 2014-01-06 | 1 |
| 2014-01-07 | 1 |
+------------+---------------+
7 rows in set (0.00 sec)
请注意,根据您需要的日历大小,您可能需要在CROSS JOINS
语句中添加更多INSERT INTO calendar
。有关示例,请参阅the link。