|
任何人都可以给我一个想法或提示如何存储登录名(用户 ID、时间戳)数据库表(MySQL)连续 中检X 天?
+ |3 @' L# T$ j. eStackoverflow 做到了(如 Enthusiast 这样的徽章-如果你连续登录 大约30天......)。你必须使用什么功能或想法?% P2 L; ^8 W9 i' J& l
像SELECT 1 FROM login_dates WHERE ...什么?8 O$ s) {4 ` L* T% k7 b& f/ f
2 v0 o6 l7 k( k6 G& e$ ^+ x 解决方案:
' q) ^+ V4 M% |+ L$ s 您可以使用移位自外连接和变量来完成此操作。请参考此解决方案:1 w2 C; x: Z+ L% a5 s
SELECT IF(COUNT(1) > 0,1,0) AS has_consecFROM( SELECT * FROM ( SELECT IF(b.login_date IS NULL,@val:=@val 1,@val) AS consec_set FROM tbl a CROSS JOIN (SELECT @val:=0) var_init LEFT JOIN tbl b ON a.user_id = b.user_id AND a.login_date = b.login_date INTERVAL 1 DAY WHERE a.user_id = 1 ) a GROUP BY a.consec_set HAVING COUNT(1) >= 30) a
, q! J6 u0 g& ?: O- r# K8 C 这将基于用户是否连续30天或以上的记录返回1或10*ANYTIME*过去。
$ C( Y) m$ v s4 T第一个查询是在第一个子选择中。让我们仔细看看,以便更好地理解它是如何工作的:
8 Q. C9 u v( }$ w' v" Q( ^9 m" u" X使用以下示例数据集:
4 d9 W9 G) N: vCREATE TABLE tbl ( user_id INT, login_date DATE);INSERT INTO tbl VALUES(1,'2012-04-01'), (2,'2012-04-(1)-04- (2)-04-(1)-05- (2)-04-(1)-05-04'), (2,'2012-05-(1)-05- (2)-05-(1)-05- (2)-05-(1)-05- (2)-05-(1)-05- (2)-05-11、-05- (2)-05-17、-05-11'), (2,'2012-05-18、-05- (2)-05-19、-05- (2)-05-二十,-05- (2)-05-21、-05- (2)-05-22、-05- (2),-05-25、-05- (2)-05-26、-05- (2)-05- -05- -05- -05-30、 -05-31'), -06-01'), -06-02');7 V0 w- D, j' I; G9 ^6 e
这个查询:0 [* \8 i6 A( l; @" Z6 _
SELECT a.*,b.*,IF(b.login_date IS NULL,@val:=@val 1,@val) AS consec_setFROM tbl aCROSS JOIN (SELECT @val:=0) var_initLEFT JOIN tbl b ON a.user_id = b.user_id AND a.login_date = b.login_date INTERVAL 1 DAYWHERE a.user_id = 1
* v. w; F: r1 I# D0 {) s0 y 将产生:, z2 }" |5 h/ n
正如你所看到的,我们正在做的是将连接表移动 1 天。每天与前一天不连续,NULLLEFT JOIN 会产生一个值。5 v6 Z- P9 v. i' g; z+ {- `
现在,我们知道在非连续的日子里,我们可以用一个变量来区分它们组通过检测转移表的行是否是连续数日NULL。如果是NULL,日期不连续,只需增加变量即可。NOT NULL,不要增加变量:; J, } ]- y& X! k' K7 R+ A! m& u
在我们用递增变量区分每组的连续天数后,我们只需按每个组(如consec_set列中定义)分组使用HAVING过滤掉任何少于指定连续天数的组(在您的示例中为 30):
+ K8 M; X! t- Q7 g- s% n! l最后,我们包装*那个*查询并简单计算连续30天或更多天的集合数。如果这些集合中有一个或多个,则返回1,否则返回0。 |
|