回答

收藏

检查连续 x 天 - 给定数据库中的时间戳

技术问答 技术问答 369 人阅读 | 0 人回复 | 2023-09-12

任何人都可以给我一个想法或提示如何存储登录名(用户 ID、时间戳)数据库表(MySQL)连续 中检X 天?% o0 u1 n8 F3 Q( m& R, b! W
Stackoverflow 做到了(如 Enthusiast 这样的徽章-如果你连续登录 大约30天......)。你必须使用什么功能或想法?
. C2 |0 A7 ^( ^/ @像SELECT 1 FROM login_dates WHERE ...什么?4 @; Y. U' l5 w  U" T
                                                                4 [# ]7 A( W$ L- p
    解决方案:                                                                2 F" E0 o8 c1 ]( l" L  T6 ?
                                                                您可以使用移位自外连接和变量来完成此操作。请参考此解决方案:* Z  w$ t% d. Y. p( r2 J" `
    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) a0 V5 R+ y7 D0 t8 G) ~# S
这将基于用户是否连续30天或以上的记录返回1或10*ANYTIME*过去。
% j) e* L% H2 a, a第一个查询是在第一个子选择中。让我们仔细看看,以便更好地理解它是如何工作的:
$ j( }$ o8 |' L% U使用以下示例数据集:
' L* o1 u! X( Y$ |9 G3 G2 g
    CREATE 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 B9 v- i$ m4 n1 C, E$ ~
这个查询:% g5 p) i+ F7 S2 C+ ?4 T
    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
    " |8 e# {" p% x  o/ j2 o1 O
将产生:
9 j6 i) `" @$ I% |' o3 g正如你所看到的,我们正在做的是将连接表移动    1 天。每天与前一天不连续,NULLLEFT JOIN 会产生一个值。: V5 g1 R+ G2 N# n$ t, K
现在,我们知道在非连续的日子里,我们可以用一个变量来区分它们组通过检测转移表的行是否是连续数日NULL。如果是NULL,日期不连续,只需增加变量即可。NOT NULL,不要增加变量:
) h8 a* X5 F7 G: X3 Y7 U% k6 e在我们用递增变量区分每组的连续天数后,我们只需按每个组(如consec_set列中定义)分组使用HAVING过滤掉任何少于指定连续天数的组(在您的示例中为 30):1 J+ ~0 D, m1 J5 X6 H0 r$ q
最后,我们包装*那个*查询并简单计算连续30天或更多天的集合数。如果这些集合中有一个或多个,则返回1,否则返回0。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则