简体   繁体   English

在连接另一个表后对MySQL结果进行排名,并按条件过滤它们

[英]Rank MySQL results after joining with another table, also filtering them by a condition

I found how to rank results, but have yet to find a solution for how to rank them after they've been filtered by a condition. 我找到了如何对结果进行排名,但还没有找到一个解决方案,以便在它们被条件过滤后对它们进行排名。 What I need to do is: 我需要做的是:

1) Sort scores in descending order 1)按降序对分数排序
2) Join the results with the account table 2)使用帐户表加入结果
3) Filter the results by age and gender (from the account table) 3)按年龄和性别(来自帐户表)筛选结果
4) Rank them 4)排名他们
5) Grab the results within a range of ranks (IE: 25-75, but I put 0-10 for simplicity below) 5)在一系列排名中获取结果(IE:25-75,但为了简单起见,我将0-10放在下面)

Each solution I've found either doesn't properly rank them, or ranks them and then filters the results. 我发现的每个解决方案要么没有对它们进行正确排名,要么对它们进行排名,然后对结果进行过滤。 However, this leaves me with ranks like 1, 3, 4, 6, 10, etc when I want 1, 2, 3, 4, 5, etc. or 25, 26, 27, 28, 29, etc. 然而,当我想要1,2,3,4,5等等或25,26,27,28,29等时,这给我留下了1,3,4,6,10等等等级。

Here is what I have right now: 这就是我现在所拥有的:

SELECT a.id, a.username, a.country, score, user_id, duration, rank
FROM (
    SELECT s.*, a.age, a.gender, @rownum := @rownum + 1 AS rank
    FROM scores s,
        (SELECT @rownum := 0) r
    LEFT JOIN accounts a ON 1
    WHERE a.age>=18 && a.age<=35 && a.gender='m'
    ORDER BY score DESC, duration DESC, time ) `selection`
LEFT JOIN accounts a ON a.id=user_id
WHERE rank >= 0 && rank <= 10 && a.age>=18 && a.age<=35 && a.gender='m'

The problem with the above query is that it gives me correct rankings without any gaps, but the scores are completely out of order. 上述查询的问题在于它给出了正确的排名,没有任何间隙,但分数完全不正常。 IE. IE浏览器。 5, 1, 10, 7, 125, 50, etc. IE. IE,1,10,7,105,50等。 They come out in the same order they are in the database, unsorted. 它们按照它们在数据库中的顺序出现,未分类。

This is what my previous query looked like: 这是我之前的查询:

SELECT a.id, a.username, a.country, score, duration, rank
FROM (
    SELECT s.*, @rownum := @rownum + 1 AS rank
    FROM scores s,
        (SELECT @rownum := 0) r
    ORDER BY score DESC, duration DESC, time ) `selection`
LEFT JOIN accounts a ON a.id=user_id
WHERE rank >= 0 && rank <= 10 && a.age>=18 && a.age<=35 && a.gender='m'

This query gives me properly sorted scores, but with ranks like 3, 5, 8, 9, 11 instead of 1, 2, 3, 4, 5. 此查询为我提供了正确排序的分数,但排名为3,5,8,9,13而不是1,2,3,4,5。

Here is some real-world sample data... 这是一些真实的样本数据......
For the sake of time, id, username, country, are all omitted because they are irrelevant data and just repeat all the way down the table. 为了节省时间,id,用户名,国家/地区都被省略了,因为它们是不相关的数据,只是在表格中一直重复。 The age all the way down is '34' just as the condition shows, the country and username are the same all the way down since this particular user is the only one in the table with the age of 34. 正如条件所示,年龄一直是'34',国家和用户名一直是相同的,因为这个特定用户是表中唯一一个年龄为34岁的用户。

The first query from above with proper rankings, but incorrectly sorted scores (IE. the same order as they were added to the database): 上面的第一个查询具有适当的排名,但排序错误(IE。与添加到数据库中的顺序相同):

  age | score | rank
--------------------
  34  |   5   |  1
  34  |   1   |  2
  34  |  22   |  3
  34  |  13   |  4
  34  |  23   |  5
  34  |  23   |  6
  34  |  34   |  7
  34  |  32   |  8
  34  |  58   |  9
  34  |  76   |  10

The second query from above, properly sorted, but ranks still take other users into consideration when ranking, then get excluded in the final result: 从上面的第二个查询,正确排序,但排名仍然考虑其他用户排名,然后在最终结果中被排除:

  age | score | rank
---------------------
  34  |  76   |  3  --- This should have started at 1
  34  |  62   |  4
  34  |  58   |  5
  34  |  42   |  7  --- Notice 6 was skipped
  34  |  34   |  8
  34  |  32   |  9
  34  |  29   |  10

What I expect: 我期待的是:

  age | score | rank
--------------------
  34  |  76   |  1
  34  |  62   |  2
  34  |  58   |  3
  34  |  42   |  4
  34  |  34   |  5
  34  |  32   |  6
  34  |  29   |  7

I can offer the following query based on your sample data set: 我可以根据您的示例数据集提供以下查询:

SET @rank = 0;
SET @score = NULL;

SELECT
    age,
    @rank:=CASE WHEN @score = score THEN @rank ELSE @rank + 1 END AS rank,
    @score:=score AS score
FROM scores
ORDER BY rank;

The computes the rank of the scores, in terms of the definition for which "rank" is usually used. 根据通常使用“等级”的定义计算得分的等级。 If two scores be the same, then they have the same rank. 如果两个分数相同,则它们具有相同的等级。 If you really want the row number, then the above query can be easily modified. 如果您确实需要行号,则可以轻松修改上述查询。

Output: 输出:

在此输入图像描述

Demo here: 在这里演示:

Rextester Rextester

SELECT a.id, a.username, a.country, score, user_id, duration, rank
FROM (
    SELECT s.*, a.age, a.gender, @rownum := @rownum + 1 AS rank
    FROM scores s,
        (SELECT @rownum := 0) r
    LEFT JOIN accounts a ON 1
    WHERE a.age>=18 && a.age<=35 && a.gender='m'
    ORDER BY score DESC, duration DESC, time ) `selection`
LEFT JOIN accounts a ON a.id=user_id
WHERE rank >= 0 && rank <= 10 && a.age>=18

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM