MySQL查询动态“排名行”

时间:2011-10-20 18:53:57

标签: mysql sql ranking

我在运行查询排名时遇到问题。 内部SELECT按排名顺序给出行,对于每一行,变量@rank增加,如果不是等于前一个等级的位置。 但@rank并不是真正的正确位置。

我正在尝试对具有最高价值的人进行分组和排序。

SET @prev := NULL;
SET @curr := NULL;
SET @rank := 0;
SELECT
    @prev := @curr,
    @curr := SUM( a.value ) AS SUM_VALUES,
    @rank := IF(@prev = @curr, @rank, @rank+1) AS rank,
    b.id AS b_id,
    b.name AS b_nome

FROM
    a INNER JOIN b ON ( a.b_id = b.id )

GROUP BY b.id
ORDER BY SUM_VALUES DESC;

结果:

----------------------------------------------------
@prev := @curr | SUM_VALUES | rank | b_id  | b_nome
---------------|------------|------|-------|--------
NULL           | 10         | 2    | 2     | BBB
NULL           | 2          | 1    | 1     | AAA

BBB在排名中排名第一,AAA排名第二。 但是这不会发生,一个关于发生了什么的想法?


测试转储

CREATE TABLE `a` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `b_id` INT(10) NULL DEFAULT NULL,
    `value` INT(10) NULL DEFAULT NULL,
    `name` VARCHAR(50) NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `b_id` (`b_id`),
    CONSTRAINT `fk_b` FOREIGN KEY (`b_id`) REFERENCES `b` (`id`)
)
ENGINE=InnoDB;

CREATE TABLE `b` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
ENGINE=InnoDB;

INSERT INTO `b` (`id`, `name`) VALUES (1, 'AAA');
INSERT INTO `b` (`id`, `name`) VALUES (2, 'BBB');

INSERT INTO `a` (`id`, `b_id`, `value`, `name`) VALUES (1, 1, 2, 'smaller');
INSERT INTO `a` (`id`, `b_id`, `value`, `name`) VALUES (2, 2, 10, 'bigger');

2 个答案:

答案 0 :(得分:3)

<强>具有
它会很慢,但是having子句将在之后运行所有选择,连接,where和group by已完成并完全解析。
唯一的问题是having不使用索引,而where确实使用索引。

SELECT
  ranking stuff
FROM 
  lot of tables
WHERE simple_condition
HAVING filters_that_run_last

明确联接
请注意,您不必混合使用显式和隐式连接 如果您想要交叉加入,则可以使用cross join关键字。

    ....
    ) AS Ranking
    CROSS JOIN (SELECT @curr := null, @prev := null, @rank := 0) InitVars
WHERE
  Ranking.regional_id = 1003

答案 1 :(得分:2)

首先,谢谢大家!

我找到了一种方法来返回预期的结果,使其他选择2

A)首先选择分组和排序

SELECT
    SUM( a.value ) AS SUM_VALUES,
    b.id AS b_id,
    b.name AS b_name
FROM
    a INNER JOIN b ON ( a.b_id = b.id )
GROUP BY b.id
ORDER BY SUM_VALUES DESC

B)我做这个排名列表

SELECT
    R.*,
   @prev := @curr,
   @curr := R.SUM_VALUES,
   @rank := IF(@prev = @curr, @rank, @rank+1) AS rank
FROM (
        SELECT
            SUM( a.value ) AS SUM_VALUES,
            b.id AS b_id,
            b.name AS b_name
        FROM
            a INNER JOIN b ON ( a.b_id = b.id )
        GROUP BY b.id
        ORDER BY SUM_VALUES DESC
) AS R

C)最后,只需选择重要的内容

SELECT
    Ranking.b_id,
    Ranking.b_name,
    Ranking.rank
FROM
(
    SELECT
        R.*,
       @prev := @curr,
       @curr := R.SUM_VALUES,
       @rank := IF(@prev = @curr, @rank, @rank+1) AS rank
    FROM (
            SELECT
                SUM( a.value ) AS SUM_VALUES,
                b.id AS b_id,
                b.name AS b_name
            FROM
                a INNER JOIN b ON ( a.b_id = b.id )
            GROUP BY b.id
            ORDER BY SUM_VALUES DESC
    ) AS R
) AS Ranking
WHERE
    Ranking.b_id = 1

此查询的结果是:

+------+--------+------+
| b_id | b_name | rank |
+------+--------+------+
|    1 | AAA    |    2 |
+------+--------+------+