MySQL中变量的意外行为

时间:2015-01-27 14:21:23

标签: mysql

我只是有一个高级时刻......这对我来说似乎违反直觉。

请考虑以下事项:

的DDL

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id CHAR(1) NOT NULL PRIMARY KEY);

INSERT INTO my_table VALUES
('a'),('b'),('c');

查询

SELECT a.id a_id
     , a.rank a_rank
     , b.id b_id
     , b.rank b_rank
  FROM 
     ( SELECT id 
            , @i := @i+1 rank
         FROM my_table 
            , (SELECT @i:=0) vars
        ORDER
           BY id
     ) a
  JOIN 
     ( SELECT id 
            , @i := @i+1 rank
         FROM my_table 
            , (SELECT @i:=0) vars
        ORDER
           BY id
     ) b;

结果

+------+--------+------+--------+
| a_id | a_rank | b_id | b_rank |
+------+--------+------+--------+
| a    |      1 | a    |      4 |
| b    |      2 | a    |      4 |
| c    |      3 | a    |      4 |
| a    |      1 | b    |      5 |
| b    |      2 | b    |      5 |
| c    |      3 | b    |      5 |
| a    |      1 | c    |      6 |
| b    |      2 | c    |      6 |
| c    |      3 | c    |      6 |
+------+--------+------+--------+

预期结果

+------+--------+------+--------+
| a_id | a_rank | b_id | b_rank |
+------+--------+------+--------+
| a    |      1 | a    |      1 |
| b    |      2 | a    |      1 |
| c    |      3 | a    |      1 |
| a    |      1 | b    |      2 |
| b    |      2 | b    |      2 |
| c    |      3 | b    |      2 |
| a    |      1 | c    |      3 |
| b    |      2 | c    |      3 |
| c    |      3 | c    |      3 |
+------+--------+------+--------+

同一个http://www.sqlfiddle.com/#!2/15f389/3

的小提琴

那么,我错过了什么?

1 个答案:

答案 0 :(得分:3)

只需在查询的两面使用不同的变量:

SELECT a.id a_id
     , a.rank a_rank
     , b.id b_id
     , b.rank b_rank
  FROM 
     ( SELECT id 
            , @i := @i+1 rank
         FROM my_table 
            , (SELECT @i:=0) vars
        ORDER
           BY id
     ) a
  JOIN 
     ( SELECT id 
            , @i1 := @i1+1 rank
         FROM my_table 
            , (SELECT @i1:=0) vars
        ORDER
           BY id
     ) b;

正在发生的是,首先运行初始化@i值的两个子查询,然后运行查询的其余部分。无法保证何时运行子查询,因此这是允许的。