有一个玩家,有输有赢,每局有记录,比如玩家 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
xuanbg 2021 年 1 月 27 日
楼主你这个需求就触及 SQL 的盲区了……
|
2
RedBeanIce 2021 年 1 月 27 日
正负这个。。。。。
|
3
no1xsyzy 2021 年 1 月 27 日
如果有一个标记顺序的字段就行(比如自动编码)
大致思路是分两步查询,第一步查询最后一个 score > 0 在哪行,第二步查出在那行之后有几行 |
4
yzdobest 2021 年 1 月 28 日 via iPhone
|
5
dswyzx 2021 年 1 月 28 日 via iPhone
思路:先通过 max(time)来获取最后一条 score 小于 0 的数据,可获得临时表:userid lasttime count=1
然后 for 循环临时表数据处理 每一个 userid+lasttime 往前面 time 读 score<0 然后 count+1 另可以设计:如果这个功能要实时统计,不如加个字段作为连输次数字段,每次插入时读取上一条记录逻辑算一下,这样如果逻辑需要处理连输的人就读上一条即可 |
6
LLLYang 2021 年 1 月 28 日
加个字段标记本局输赢情况不好么
|
7
weizhen199 2021 年 1 月 28 日
lz 应该不是做统计的吧。
前台用的话 decode + open window 应该就可以了 慢的话,给 decode 列加上函数索引。 |
8
Rache1 2021 年 1 月 28 日
用 Redis 的 BitMap 来做~
|
9
sarices 2021 年 1 月 28 日
```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; ``` |
10
gwbw 2021 年 1 月 28 日
可能部分时序数据库有办法做,看看 timescaledb
|
11
liuzhen 2021 年 1 月 28 日
这个需求和统计用户连续签到天数基本一致,网上能找到 sql
|
12
F281M6Dh8DXpD1g2 2021 年 1 月 28 日
这个问题不就是在所有输的记录里面找到连续的么
|
13
bugmakerxs 2021 年 1 月 28 日
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 的行数量 |
15
lbmjsls1 OP @bugmakerxs 这种方法也不对,首先你应该说反了,找到最小的 id 或者小于最大的 id,另外,同样不能保证找到的这个 id 就是最后一条数据
|
16
lbmjsls1 OP @liuzhen 连续签到的也不行,连续签到的少了一个条件,也就是插入到数据库的数据肯定是有效的,可以使用判断连续了多少次,而输赢的是插入的数据有输的,有赢的,如果过滤掉其中的赢的,就是连续签到的问题,但是不符合我的需求
|
19
c6h6benzene 2021 年 1 月 28 日 via iPhone
count over partition by 胜负 order by 时间也许可解
|
20
no1xsyzy 2021 年 1 月 28 日
|
21
no1xsyzy 2021 年 1 月 28 日
@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 但注意事务隔离级别,不可重复读会有问题。 |
22
no1xsyzy 2021 年 1 月 28 日
草了,我还是把 < > 弄反了……
X | reverse | takewhile _ => _.score < 0 | len 等效于 X | after (X | last _ => not _.score < 0) | len |
23
bugmakerxs 2021 年 1 月 28 日
@lbmjsls1 你再捋一捋,我看了半天没懂你回复我的是什么意思。
|
24
bugmakerxs 2021 年 1 月 28 日
@lbmjsls1 我这个 sql 应该没问题
|
27
lbmjsls1 OP @bugmakerxs 这个思路是对的,我想反了,不过有情况不对,就是如果玩家全是输的,那么就没有最后一个 id,那么统计下来就是 0.
|
28
NeezerGu 2021 年 1 月 28 日
hive 可以
窗口函数加个 if, 再 row_number() over() 一下应该能出来 |
30
sarices 2021 年 1 月 28 日
@lbmjsls1 不好意思,没看清楚你的问题,以为是计算胜负而已,参照这篇文章,应该可以解决你的问题 https://blog.csdn.net/u013887008/article/details/89105994
|
31
kiracyan 2021 年 1 月 28 日
从游玩记录里统计有点费事 直接在用户表加一个字段插入游玩记录的时候更新
|
32
bugmakerxs 2021 年 1 月 28 日
@lbmjsls1 嗯,那就里边 sql 加个判断,如果为 null 则设置为 0 就好了。
|