2011-10-20 14 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 | 
+------+--------+------+ 
関連する問題