我有一个包含以下数据的表(仅作为示例,实际表有600,000行)(aid =访问ID [主键]和id =用户ID [外键]):
aid | id | date
332 | 1 | 2016-12-15
331 | 4 | 2016-12-15
330 | 3 | 2016-12-15
329 | 1 | 2016-12-14
328 | 1 | 2016-12-14
327 | 2 | 2016-12-14
326 | 3 | 2016-12-13
325 | 2 | 2016-12-13
324 | 1 | 2016-12-13
323 | 1 | 2016-12-12
322 | 3 | 2016-12-12
321 | 1 | 2016-12-12
每个id都是用户主键,每次他们访问我的系统中的某些内容时,我都会在这个表中记录它们(日期格式如图所示,以及它们的id)。用户可以每天多次登录。
我希望:返回一天内访问该事物的总次数,并返回过去8天内访问该事物的新用户总数(有些事情总是如此)每天记录,所以使用“LIMIT 8”只能获得最近8天。)
我的SQL目前看起来像:
SELECT COUNT(id), COUNT(distinct id), date
FROM table
GROUP BY date
ORDER BY date DESC
LIMIT 8;
SQL正确地完成了第一部分,但我无法弄清楚如何让它返回那天从未访问过该东西的用户数。
期望的结果是,一个“newuser”代表id为“4”的用户,因为他们之前从未访问过该东西:
COUNT(id) | newusers | date
3 | 1 | 2016-12-15
3 | 0 | 2016-12-14
3 | 0 | 2016-12-13
3 | 0 | 2016-12-12
很抱歉,如果我没有说清楚这一点。
答案 0 :(得分:1)
要获取新用户的数量,您需要将其与过去8天内的一组ID进行比较
我的MySQL有点生疏,所以你可能需要纠正语法。
SELECT COUNT(id)
FROM table
WHERE id NOT IN (
SELECT DISTINCT id
FROM table
WHERE date BETWEEN DATE(DATE_SUB(NOW(), INTERVAL 8 DAY)) AND DATE(DATE_SUB(NOW(), INTERVAL 1 DAY))
)
我将此作为一项任务让您将其与其他查询相结合;)
答案 1 :(得分:1)
如果数据库中的日期列是日期时间/日期或代表格式的其他日期,您可以这样做:
让所有在8天内访问过某些内容的用户:
Select id, date from table
where date BETWEEN DATE_ADD(NOW(), INTERVAL -9 DAY) AND NOW()
我认为,你可以做任何你想要的分组。 要获得新用户,您可以选择自我加入或使用子选择
selfjoin:
select t.id, t.date from table as t
LEFT join table as t2
ON t.id = t2.id
AND t.date BETWEEN DATE_ADD(NOW(), INTERVAL -1 DAY) AND NOW()
AND t2.date NOT BETWEEN DATE_ADD(NOW(), INTERVAL -9 DAY) AND NOW()
WHERE t2.id IS NULL
我使用左连接来匹配用户的所有访问权限,然后排除那些行。但是,自连接速度很慢,使用LEFT join
时速度更慢子选择:
select id, date from table
where date BETWEEN DATE_ADD(NOW(), INTERVAL -1 DAY) AND NOW()
AND id NOT IN (
SELECT id FROM table
WHERE date BETWEEN DATE_ADD(NOW(), INTERVAL -2 DAY) AND DATE_ADD(NOW(), INTERVAL -1 DAY)
)
我知道那些带有date_adds的玩家并不是很好看,但我希望它能帮助你更多地分组日期
我建议使用日期和时间来获取更多信息,但这完全取决于您的数据含义
答案 2 :(得分:1)
要获得新用户,您希望第一天出现ID:
select id, min(date)
from t
group by id;
剩下的就是join
和group by
:
select d.date, cnt, count(dd.id) as newusers
from (select date, count(*) as cnt
from t
group by date
) d left join
(select id, min(date) as mindate
from t
group by id
) dd
on d.date = dd.mindate
group by d.date, d.cnt
limit 8;