最新连续输的 sql 统计 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
lbmjsls1
V2EX    MySQL

最新连续输的 sql 统计

  •  
  •   lbmjsls1 2021-01-27 22:34:01 +08:00 4104 次点击
    这是一个创建于 1788 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个玩家,有输有赢,每局有记录,比如玩家 id 是 userid,输赢根据得分字段 score 正负判断,如何写一个 sql 语句统计最近的连续输的次数。

    比如

    userid score

    12345 100

    12345 -100

    12345 100

    统计出来是 0

    userid score

    12345 100

    12345 -100

    12345 -100

    统计出来是 2

    userid score

    12345 -100

    12345 100

    12345 -100

    统计出来是 1

    第 1 条附言    2021-01-28 11:57:03 +08:00
    根据 @bugmakerxs 暂时修改了一下,测试下来没发现问题,大家帮忙看一下有没有漏洞

    select count(1) from test where userid=2222 and id > IFNULL((
    select id from test where userid=2222 and score > 0 order by id desc limit 1
    ), 0)
    第 2 条附言    2022-06-02 09:27:18 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    第 3 条附言    2022-06-02 09:27:23 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    第 4 条附言    2022-06-02 09:27:26 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    第 5 条附言    2022-06-02 09:27:40 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    第 6 条附言    2022-06-02 09:27:45 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    第 7 条附言    2022-06-02 09:27:49 +08:00
    是豆腐干山豆根山豆根山豆根山豆根士大夫 v 复古如图一要让他也让豆腐干豆腐干恢复人文 34 同仁堂也让图与体育体育风格恢复举报你不更符合瑞特瑞特让他感到给对方
    32 条回复    2021-01-28 12:12:32 +08:00
    xuanbg
        1
    xuanbg  
       2021-01-27 23:30:08 +08:00
    楼主你这个需求就触及 SQL 的盲区了……
    RedBeanIce
        2
    RedBeanIce  
       2021-01-27 23:31:24 +08:00
    正负这个。。。。。
    no1xsyzy
        3
    no1xsyzy  
       2021-01-27 23:59:47 +08:00
    如果有一个标记顺序的字段就行(比如自动编码)
    大致思路是分两步查询,第一步查询最后一个 score > 0 在哪行,第二步查出在那行之后有几行
    yzdobest
        4
    yzdobest  
       2021-01-28 00:05:31 +08:00 via iPhone
    https://mp.weixin.qq.com/s/d0fdqAzCE9FopNWBcMSYnw
    楼主可以参考下这篇文章
    dswyzx
        5
    dswyzx  
       2021-01-28 01:34:11 +08:00 via iPhone
    思路:先通过 max(time)来获取最后一条 score 小于 0 的数据,可获得临时表:userid lasttime count=1
    然后 for 循环临时表数据处理 每一个 userid+lasttime 往前面 time 读 score<0 然后 count+1

    另可以设计:如果这个功能要实时统计,不如加个字段作为连输次数字段,每次插入时读取上一条记录逻辑算一下,这样如果逻辑需要处理连输的人就读上一条即可
    LLLYang
        6
    LLLYang  
       2021-01-28 08:40:39 +08:00
    加个字段标记本局输赢情况不好么
    weizhen199
        7
    weizhen199  
       2021-01-28 09:00:41 +08:00
    lz 应该不是做统计的吧。

    前台用的话 decode + open window 应该就可以了

    慢的话,给 decode 列加上函数索引。
    Rache1
        8
    Rache1  
       2021-01-28 09:26:23 +08:00
    用 Redis 的 BitMap 来做~
    sarices
        9
    sarices  
       2021-01-28 09:26:59 +08:00
    ```sql
    SELECT
    userid,
    count( CASE score>0 WHEN TRUE THEN 1 END ) AS victory,
    count( CASE score<0 WHEN TRUE THEN 1 END ) AS failure
    FROM
    tablename
    GROUP BY
    userid;
    ```
    gwbw
        10
    gwbw  
       2021-01-28 09:55:42 +08:00
    可能部分时序数据库有办法做,看看 timescaledb
    liuzhen
        11
    liuzhen  
       2021-01-28 10:01:01 +08:00
    这个需求和统计用户连续签到天数基本一致,网上能找到 sql
    F281M6Dh8DXpD1g2
        12
    F281M6Dh8DXpD1g2  
       2021-01-28 10:07:08 +08:00
    这个问题不就是在所有输的记录里面找到连续的么
    bugmakerxs
        13
    bugmakerxs  
       2021-01-28 10:16:45 +08:00
    select count(1) from user_score where userid=1 and id > (
    select id from user_score where userid=1 and score > 0 order by id desc limit 1
    )

    内层找到 score>0 的最大 id
    外层统计大于这个 id 的行数量
    lbmjsls1
        14
    lbmjsls1  
    OP
       2021-01-28 10:30:41 +08:00
    @sarices 这种方法不对,不是求历史连输的记录,是求最新连输的记录
    lbmjsls1
        15
    lbmjsls1  
    OP
       2021-01-28 10:35:32 +08:00
    @bugmakerxs 这种方法也不对,首先你应该说反了,找到最小的 id 或者小于最大的 id,另外,同样不能保证找到的这个 id 就是最后一条数据
    lbmjsls1
        16
    lbmjsls1  
    OP
       2021-01-28 10:43:12 +08:00
    @liuzhen 连续签到的也不行,连续签到的少了一个条件,也就是插入到数据库的数据肯定是有效的,可以使用判断连续了多少次,而输赢的是插入的数据有输的,有赢的,如果过滤掉其中的赢的,就是连续签到的问题,但是不符合我的需求
    sarices
        17
    sarices  
       2021-01-28 10:49:43 +08:00
    对的,tablename 是最新记录子查询就好了
    @lbmjsls1
    sarices
        18
    sarices  
       2021-01-28 10:50:42 +08:00
    @lbmjsls1 如果你不会,创建一个最新记录的视图也行,tablename 改为视图名称
    c6h6benzene
        19
    c6h6benzene  
       2021-01-28 10:54:45 +08:00 via iPhone
    count over partition by 胜负 order by 时间也许可解
    no1xsyzy
        20
    no1xsyzy  
       2021-01-28 11:00:26 +08:00
    @lbmjsls1 #13 就是我 #2 的思路。
    没反,是你僵掉了

    就是 reversed takewhile,放 SQL 里就是 count before first not
    no1xsyzy
        21
    no1xsyzy  
       2021-01-28 11:04:10 +08:00
    @no1xsyzy
    就是 reversed takewhile len,放 SQL 里就是 count after last not
    换一下代码:
    Given series X

    X | reverse | takewhile _ => _.score > 0 | len
    等效于
    X | after (X | last _ => not _.score > 0) | len

    但注意事务隔离级别,不可重复读会有问题。
    no1xsyzy
        22
    no1xsyzy  
       2021-01-28 11:05:42 +08:00
    草了,我还是把 < > 弄反了……

    X | reverse | takewhile _ => _.score < 0 | len
    等效于
    X | after (X | last _ => not _.score < 0) | len
    bugmakerxs
        23
    bugmakerxs  
       2021-01-28 11:10:48 +08:00
    @lbmjsls1 你再捋一捋,我看了半天没懂你回复我的是什么意思。
    bugmakerxs
        24
    bugmakerxs  
       2021-01-28 11:13:01 +08:00
    @lbmjsls1 我这个 sql 应该没问题
    liuzhen
        25
    liuzhen  
       2021-01-28 11:21:37 +08:00
    @lbmjsls1 你这个需求为什么加个字段记录连续输 /赢次数,在插入输赢的时候做个判断上次是输 /赢,来累加这个字段的次数呢?
    lbmjsls1
        26
    lbmjsls1  
    OP
       2021-01-28 11:51:28 +08:00
    @sarices 我又试了一边,这个确实是不对的,你写几个测试例子试试
    lbmjsls1
        27
    lbmjsls1  
    OP
       2021-01-28 11:52:50 +08:00
    @bugmakerxs 这个思路是对的,我想反了,不过有情况不对,就是如果玩家全是输的,那么就没有最后一个 id,那么统计下来就是 0.
    NeezerGu
        28
    NeezerGu  
       2021-01-28 11:55:25 +08:00
    hive 可以

    窗口函数加个 if, 再 row_number() over() 一下应该能出来
    dswyzx
        29
    dswyzx  
       2021-01-28 12:00:24 +08:00 via iPhone
    @lbmjsls1 #27 判断 isnull 呀,不存在置为 0
    sarices
        30
    sarices  
       2021-01-28 12:01:17 +08:00
    @lbmjsls1 不好意思,没看清楚你的问题,以为是计算胜负而已,参照这篇文章,应该可以解决你的问题 https://blog.csdn.net/u013887008/article/details/89105994
    kiracyan
        31
    kiracyan  
       2021-01-28 12:01:50 +08:00
    从游玩记录里统计有点费事 直接在用户表加一个字段插入游玩记录的时候更新
    bugmakerxs
        32
    bugmakerxs  
       2021-01-28 12:12:32 +08:00
    @lbmjsls1 嗯,那就里边 sql 加个判断,如果为 null 则设置为 0 就好了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     931 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 18:50 PVG 02:50 LAX 10:50 JFK 13:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86