我有一个包含字段id, user_id, condition1, condition2, condition3, score
的表格。每个用户可以在表中有多行。我现在要做的是创建几个顶级列表。例如,它可能是condition1 = foo
的顶级列表,我只想计算每个用户一次,但我希望每个用户都有完整的最佳行。
所以SELECT user_id, MAX(score) AS s FROM table WHERE condition1 = foo ORDER BY s DESC LIMIT 50
不起作用。
我想要这么多不同的名单,所以创建第二个表,我存储用户最好的结果不是一个真正的选择。因为每个用户可能会有超过100个不同的最佳结果。
重要的两件事是快速获得前50名。但是还要确定特定用户所处的位置(通过检查有多少独特用户得分高于特定用户,这非常容易)。
更新:我测试了Thomas和Quassnoi的想法,Thomas的想法用了11秒,Quassnoi用了4.5秒。
然后我想出了另一种方法:
SELECT (
SELECT id
FROM table AS ti
WHERE ti.user_id = t.user_id
AND condition1 = foo
ORDER BY score DESC
LIMIT 1
)
FROM table as t
WHERE condition1 = foo
GROUP BY user_id
ORDER BY MAX(score) DESC
LIMIT 50
然后我再做一个查询,其中挑选出所有行WHERE id IN(all ids returned from the first query)
,这种方式需要0.4秒。
这是一个很好的方法吗?或者我只是在我的testdata中幸运?
答案 0 :(得分:0)
未经测试,但我认为您缺少GROUP BY子句:
SELECT user_id, MAX(score) AS s FROM table WHERE condition1 = foo GROUP BY user_id ORDER BY s DESC LIMIT 50
答案 1 :(得分:0)
SELECT *
FROM mytable m
WHERE m.id =
(
SELECT id
FROM mytable mi
WHERE mi.user_id = m.user_id
AND mi.condition1 = 'foo'
ORDER BY
score DESC, id DESC
LIMIT 1
)
ORDER BY
score DESC
LIMIT 50
或
SELECT m.*
FROM users u
JOIN mytable m
ON mi.id =
(
SELECT id
FROM mytable mi
WHERE mi.user_id = u.id
ORDER BY
score DESC, id DESC
LIMIT 1
)
ORDER BY
score DESC
LIMIT 50
哪一个更快取决于分数的分布,但第一个分数通常更快,除非你真的很少有很多分数的用户真正经常联系。
为了使其快速起作用,您应该使用复合索引:
mytable (score, id)
加上每个过滤组合的索引,如下所示:
mytable (user_id, score, id) -- for no filtering
mytable (user_id, condition1, score, id) -- for filtering on condition1
等
答案 2 :(得分:0)
Select T.Id, T.user_id, T.condition1, T.condition2, T.condition3, T.score
From Table As T
Where Exists (
Select 1
From Table As T2
Where T2.user_id = T.user_id
And T2.condition1 = 'foo'
Having Max(T2.score) = T.score
)
Limit 50