2011-10-20 90 views
1

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

我试图做一个排名分组和按最高价值排序。

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'); 
+0

结果是什么,你要* *?这不是很清楚。此外,它还可以帮助将您的示例简化为一个非常简单的数据集,它可以演示您的问题,而无需使用与问题无关的一堆表,列和过滤器。这个问题有太多可以处理,这可能是你为什么没有得到任何回应。 – mellamokb

+0

好的,我试图简化 –

回答

3


这将是缓慢的,但having子句将运行所有的选择,联接,地点和组通过的已经完成,并完全解决。
唯一的问题是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 
+0

谢谢。看看我所做的,以带来预期的结果... = P ...再一次,谢谢 –

+0

你很好! –

1

首先,谢谢大家!

我找到了一种方法,以返回预期的结果进行其他选择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 | 
+------+--------+------+