【问题标题】:MySQL query to dynamic "Ranking rows"MySQL查询动态“排名行”
【发布时间】:2011-12-12 01:10:07
【问题描述】:

我在运行查询排名时遇到问题。 内部 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');

【问题讨论】:

  • 想要的结果是什么?这还不是很清楚。它还可以帮助将您的示例简化为一个非常简单的数据集,该数据集可以演示您的问题,而没有一堆与问题无关的表、列和过滤器。这个问题有太多要处理的问题,这可能是您没有得到任何回复的原因。

标签: mysql sql ranking


【解决方案1】:

拥有
这会很慢,但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

【讨论】:

  • 谢谢。看看我所做的带来预期的结果...... =P......再次,谢谢你
【解决方案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 |
+------+--------+------+

【讨论】:

    猜你喜欢
    • 2012-12-30
    • 2020-05-26
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    相关资源
    最近更新 更多