关于结果匹配的Mysql查询不起作用

时间:2017-03-23 08:27:20

标签: mysql inner-join

我的简单表格以这种方式(4个字段)和超过100行格式化:

id结果id_user数据

1 0 11 2016-10-15 18:00:00
2 0 13 2016-10-15 18:00:00
3 0 16 2016-10-15 18:00:00
4 0 24 2016-10-15 18:00:00
5 0 6 2016-10-15 18:00:00
6 3 3 5 2016-10-15 18:00:00
7 3 45 2016-10-15 18:00:00
8 3 3 66 2016-10-15 18:00:00
9 3 4 2016-10-15 18:00:00 < br /> 10 3 33 2016-10-8 17:00:00
11 1 55 2016-10-8 17:00:00
12 1 101 2016-10-8 17:00:00

...

我每周用这个逻辑保存10条记录: 如果一支球队获胜,我将为球队的每个成员节省3分,为球队的每个成员保留0分。 (如果他们抽签,我将为所有10名成员保存1分),依此类推。

现在我的问题是如何提取保存在此表中的前3名球员,至少打了5场比赛,并且在最后5场比赛中有主要得分。

我用这种方式格式化了我的查询:

(SELECT m1.id_user, m1.data, SUM(result) AS ris 
FROM my_table m1 
JOIN(SELECT id_user 
      FROM my_table 
      GROUP BY id_user 
      HAVING COUNT(id_user) >= 5) m2 
ON m2.id_user = m1.id_user 
GROUP BY id_user 
ORDER BY m1.data DESC) 
ORDER BY ris DESC LIMIT 3;

但是这个查询考虑了所有比赛中的得分量,而不仅仅是最近5场比赛!如果有可能,如何在我的查询中插入这个条件?

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您可以尝试将SUM(结果)放到子查询中。

SELECT m1.id_user,m1.data,result AS ris from my_table m1  JOIN(SELECT id_user, SUM(result)as result FROM my_table GROUP BY id_user HAVING COUNT(id_user)&gt; = 5)m2 ON m2.id_user = m1.id_user GROUP BY id_user  ORDER BY m1.data DESC  )ORDER BY ris DESC LIMIT 3;

答案 1 :(得分:0)

实际上并没有一种非常有效的方法,但即使没有MySQL支持窗口函数,它也是可能的。它有助于保持简单,分数是单个数字,并且只有两个可能的非零分数。

select id_user, 
    3*length(replace(replace(left(group_concat(result order by data desc separator ''), 5), '0', ''), '1', ''))
        +length(replace(replace(left(group_concat(result order by data desc separator ''), 5), '0', ''), '3', '')) 
        as score_sum 
from my_table 
group by 1 
having count(*) >= 5 
order by 2 desc 
limit 3;

打破它:

group by 1group by id_user的缩写(select中的第一个值),因此每个用户只返回一行。

group_concat(result order by data desc separator '')连接用户的所有分数,最近一次,没有在它们之间添加分隔符字符串,为用户生成类似'033101003'的字符串。 group_concat将在某个(可配置的)长度之后截断数据并产生警告,但这不是关注的问题。

left(..., 5)为用户提供最左边(最近)的五个分数(例如'03310')。

replace(...,'0','')删除0,所以上面的例子变成'331'。

我们通过取这个字符串计算多少3个,用''替换1'(生成'33'),然后取长度(2)。

同样地,我们通过取这个字符串计算多少1,用''(生成'1')替换3'并取长度(1)。

3*...+...通过将3的数量加到1的数量上来计算得分的总和(2 * 3 + 1是0,3,3,1中最近五个得分的7的总和) ,0,1,0,0,3)。

我采用这种方法,因为只有两个非零分数要处理。如果有更多,我会使用不同的计数技巧。而不是删除我不想要的数字,我会计算我做的那些。你这样说(length(string)-length(replace(string,searchstring,'')))/length(searchstring)。例如。要计算abccbacba中的c,你删除c(产生abbaba)并从原始字符串的长度中减去(6)的长度(9,得到3的结果)。