【问题标题】:MySQL SET rank over First Column and Second ColumnMySQL SET 排名高于第一列和第二列
【发布时间】:2017-10-10 07:29:32
【问题描述】:

我正在尝试按第一列和第二列进行查询设置排名列。比如 Rank over Partition 不存在 MySQL

例如,

来自

+----+-------+--------+------+
| id | First | Second | Rank |
+----+-------+--------+------+
|  1 | a     |     10 |      |
|  2 | a     |      9 |      |
|  3 | b     |     10 |      |
|  4 | b     |      7 |      |
|  5 | a     |      1 |      |
|  6 | b     |      1 |      |
+----+-------+--------+------+

+----+-------+--------+------+
| id | First | Second | Rank |
+----+-------+--------+------+
|  1 | a     |     10 |    3 |
|  2 | a     |      9 |    2 |
|  3 | b     |     10 |    3 |
|  4 | b     |      7 |    2 |
|  5 | a     |      1 |    1 |
|  6 | b     |      1 |    1 |
+----+-------+--------+------+

排名不会继续。当它到达'First'列的'a'的最后一个值时,它再次从1开始。

而且它必须是 SET 而不是 SELECT。 我不介意使用 SELECT,但我的意思是我不是试图从数据库中检索数据,而是设置值。

朋友们提前干杯。

【问题讨论】:

  • 但为什么要存储派生数据?
  • 每次要求都无法订购
  • 我不明白。费用是多少?
  • 我的 Django 服务器每次请求时都无法订购表格。因为它可以是每分钟一千次。所以我的团队决定将排名数据存储在表格列中。因为“select rank where id= x”会比对每一行排序要快得多。

标签: mysql set rank partition


【解决方案1】:
DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,first CHAR(1) NOT NULL
,second INT NOT NULL
);

INSERT INTO my_table VALUES
(1,'a',10),
(2,'a',9),
(3,'b',10),
(4,'b',7),
(5,'a',1),
(6,'b',1);

SELECT id
     , first
     , second
     , rank 
  FROM 
     ( SELECT x.* 
            , CASE WHEN @prev = first THEN @i:=@i+1 ELSE @i:=1 END rank
            , @prev:=first 
         FROM my_table x
            , (SELECT @prev:=null,@i:=0) vars 
        ORDER 
           BY first
            , second
            , id
     ) a
 ORDER 
    BY id;
+----+-------+--------+------+
| id | first | second | rank |
+----+-------+--------+------+
|  1 | a     |     10 |    3 |
|  2 | a     |      9 |    2 |
|  3 | b     |     10 |    3 |
|  4 | b     |      7 |    2 |
|  5 | a     |      1 |    1 |
|  6 | b     |      1 |    1 |
+----+-------+--------+------+
6 rows in set (0.00 sec)

【讨论】:

  • 除了删除表还有其他解决方案吗??
  • 天哪,我放弃了。用头撞墙的表情符号在哪里?
  • 非常感谢您的尝试。我只是想让我的老板满意,这样我就可以就更好的职位谈判薪水。
  • 我会减薪吗?
【解决方案2】:

想出了我一直在寻找的解决方案。 我不确定这些查询是否完全安全,但到目前为止没有任何危害。

SET @rank = 0, @First = ''
UPDATE 'Table' SET 
rank = IF(@First = First, @rank:= @rank +1, @rank := 1 AND @First := First)
ORDER BY First ASC, Second;

【讨论】:

    【解决方案3】:

    一种方法是相关子查询。对于rank(),您可以这样做:

    select t.*,
           (select count(*) + 1
            from t t2
            where t2.first = t.first and t2.second < t.second
           ) as rank
    from t;
    

    使用变量处理排名很棘手(dense_rank()row_number() 更简单)。

    编辑:

    这很容易变成update

    update t join
           (select t.*,
                   (select count(*) + 1
                    from t t2
                    where t2.first = t.first and t2.second < t.second
                   ) as new_rank
            from t
           ) tt
           on t.id = tt.id
        set t.rank = tt.new_rank;
    

    【讨论】:

    • 感谢您的想法,但正如我提到的,它必须是更新而不是选择
    猜你喜欢
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 2023-01-22
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    相关资源
    最近更新 更多