如果有更多项目共享第3个最高值,SQL会选择前3个或更多?

时间:2014-04-05 16:13:21

标签: mysql sql

任何可以解释我如何选择的SQL专家都会说出前三项。当第3项等于第4项和第5项时,我也喜欢那些,但仅限于那种情况。例如以下列表

40,
30,
15,
15,
15,
10

它会返回40,30,15,15,15而不是40,30,15。

2 个答案:

答案 0 :(得分:1)

如果您只想输出得分字段,可以这样做:

SET @ranks = 3;

PREPARE stmt_top3 FROM
    'SELECT score FROM (
        SELECT score, (@row := @row + 1), IF (@row = ?, @min_score := score, NULL)
            FROM user_score
            WHERE score IN (
                SELECT top_score.score FROM (
                    SELECT DISTINCT score,
                    (@row := 0), (@min_score := 0)
                        FROM user_score
                        ORDER BY score DESC
                        LIMIT ?
                ) AS top_score
            )
            ORDER BY score DESC
        ) AS score_rows
        WHERE score >= @min_score
        ORDER BY score DESC';

EXECUTE stmt_top3 USING @ranks, @ranks;

DEMO @ SQL Fiddle

我使用了准备好的声明,因此显示的排名数量是灵活的。如果您不想要,只需硬编码3而不是2 ?

否则,如果您还需要排名和user_id,即这里有更广泛的方法:

高分排名(共享排名)

选择共享第一个排名的所有行,无论有多少行。 只要这些行的数量不大于或等于允许的最大等级(在您的示例中为3),下一个等级就是行数+ 1。 一切都从一开始就等等......

SET @ranks = 3;

PREPARE stmt_top3 FROM
    'SELECT user_score.user_id, score_rank.rank, score_rank.score
        FROM user_score
        INNER JOIN (
            SELECT (@last_rank := @last_rank + @last_equal_score) AS rank,
                score, (@last_equal_score := count(score)) AS equal_score
                FROM user_score
                WHERE score IN (
                    SELECT top_score.score FROM (
                        SELECT DISTINCT score,
                        (@last_rank := 1), (@last_equal_score := 0)
                            FROM user_score
                            ORDER BY score DESC
                            LIMIT ?
                    ) AS top_score
                )
                GROUP BY score
                ORDER BY score DESC
        ) AS score_rank
        ON user_score.score = score_rank.score
        WHERE score_rank.rank <= ?
        ORDER BY score_rank.rank ASC';

EXECUTE stmt_top3 USING @ranks, @ranks;

DEMO @ SQL Fiddle

由于MySQL在某些子查询运算符(如LIMIT)的子查询中不支持IN,因此必须在另一个简单子查询中包含包含LIMIT子句的子查询避免以下错误:

  

ERROR 1235(42000):这个版本的MySQL还没有支持&#39; LIMIT   &安培; IN / ALL / ANY / SOME子查询&#39;

Restrictions on Subqueries

我使用以下设置进行测试:

CREATE TABLE user (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;

INSERT INTO user (id) VALUES
    (NULL),
    (NULL),
    (NULL),
    (NULL),
    (NULL),
    (NULL);

CREATE TABLE user_score (
    user_id INT UNSIGNED NOT NULL UNIQUE,
    score INT NOT NULL DEFAULT 0,
    INDEX (score),
    FOREIGN KEY (user_id) REFERENCES user (id)
) ENGINE=InnoDB;

INSERT INTO user_score (user_id, score) VALUES
    (1, 40),
    (2, 30),
    (3, 15),
    (4, 15),
    (5, 15),
    (6, 10);

答案 1 :(得分:1)

SELECT * 
FROM myTable
WHERE Field1 IN(
    SELECT * 
    FROM (
        SELECT DISTINCT Field1 
        FROM myTable
        ORDER BY Field1 DESC
        LIMIT 3)
    ) t

你可能从你的例子中得到的唯一问题是,如果你特别想要包含40&amp; D的复制品。 30?