mysql - 用变量模拟 row_number 忽略顺序

标签 mysql sql user-variables

我正试图帮助解决这个问题 Selecting rows based on a few rules

想法是为每个用户选择语言匹配@lenguage 的行 ID,否则选择创建的第一种语言。

因为没有row_number(),不得不使用用户变量。假设我添加了一个字段 test_id,这样就可以将所有案例放在同一个表中。

SQL DEMO

  SELECT t.* , (`language` = @language) as tt,
         @rn := if (@partition = CONCAT(`test_id`, '-', `user`),
                    @rn + 1,
                    if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
                   ) as rn,
         @partition           
  FROM Table1 t
  CROSS JOIN ( SELECT @language := 'de', @rn := 0, @partition := '' ) as var
  ORDER BY CONCAT(`test_id`, '-', `user`), 
           (`language` = @language) DESC,
           `created`

输出

但是即使 ORDER BY 给出了正确的排序,分区 1-43-4 也不会把语言 'de' 作为第一个。所以有些东西正在改变变量 @rn 的分配方式。

| test_id | id | title | language |              created | user | tt | rn | @partition |
|---------|----|-------|----------|----------------------|------|----|----|------------|
|       1 |  3 |     c |       de | 2019-01-03T00:00:00Z |    4 |  1 |  3*|        1-4 |
|       1 |  1 |     a |       en | 2019-01-01T00:00:00Z |    4 |  0 |  1 |        1-4 |
|       1 |  2 |     b |       es | 2019-01-02T00:00:00Z |    4 |  0 |  2 |        1-4 |
|       2 |  1 |     a |       en | 2019-01-01T00:00:00Z |    4 |  0 |  1 |        2-4 |
|       2 |  2 |     b |       es | 2019-01-02T00:00:00Z |    4 |  0 |  2 |        2-4 |
|       3 |  1 |     a |       en | 2019-01-01T00:00:00Z |    3 |  0 |  1 |        3-3 |
|       3 |  3 |     b |       de | 2019-01-03T00:00:00Z |    4 |  1 |  2*|        3-4 |
|       3 |  2 |     b |       es | 2019-01-02T00:00:00Z |    4 |  0 |  1 |        3-4 |
|       3 |  4 |     c |       de | 2019-01-04T00:00:00Z |    5 |  1 |  1 |        3-5 |

最佳答案

在选择所有行后完成排序。您的 @rn 变量是在行选择期间设置的,因此它使用行的内部顺序,而不是您的 ORDER BY 子句中指定的顺序。

您需要将排序移动到子查询中,然后在主查询中计算@rn

  SELECT t.*,
         @rn := if (@partition = CONCAT(`test_id`, '-', `user`),
                    @rn + 1,
                    if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
                   ) as rn,
         @partition           
  FROM (
    SELECT *, (language = @language) AS tt
    FROM Table
    CROSS JOIN (SELECT @language := 'de') AS var
    ORDER BY CONCAT(test_id, '-', user),
            tt DESC,
            created
  ) AS t
  CROSS JOIN ( SELECT @rn := 0, @partition := '' ) as var

关于mysql - 用变量模拟 row_number 忽略顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57317471/

相关文章:

sql - Mysql - 帮我优化这个查询(改进的问题)

sql - 左连接充当内部连接?

mysql - 由于用户变量太长而无法运行准备好的语句?

MySQL DELETE 语句在 where-in 子句中包含用户变量?

mysql - 简单连接导致使用大量行

mysql - 使用命令行将 my.cnf 文件复制到 Mysql 目录

java - JSP/SQL 语法 - 在语句中使用变量

mysql - 跨多个表的SQl查询计算

php - 在 PHP 中从类别循环到子类别

MySQL 用户为每个特定 ID 定义变量