不能在 mysql 函数中使用别名作为 ORDER BY 子句的一部分

Can't use alias in mysql function as part of ORDER BY clause

如果我执行以下查询,它工作正常。

SELECT 
CASE WHEN description LIKE '%a%' THEN 'A'
        WHEN description LIKE '%b%' THEN 'B'
        ELSE 'C'
    END AS foo
,COUNT(*) AS cnt
FROM product p
GROUP BY foo
ORDER BY foo;

结果类似于

foo  |  cnt
-----------
A    |  809
B    |   29
C    |   55

但是,下面的查询给出了一个错误。请注意,我只更改了最后一行。

SELECT 
CASE WHEN description LIKE '%a%' THEN 'A'
        WHEN description LIKE '%b%' THEN 'B'
        ELSE 'C'
    END AS foo
,COUNT(*) AS cnt
FROM product p
GROUP BY foo
ORDER BY FIELD(foo, 'A', 'B', 'C');    -- Different line

SQL Error (1054): Unknown column 'foo' in 'order clause'

这是为什么?

我正在使用 MySQL 版本 5.0.22

更新:

只是为了扩展,如果我省略分组,我会看到相同的行为,即:

SELECT 
CASE WHEN description LIKE '%a%' THEN 'A'
        WHEN description LIKE '%b%' THEN 'B'
        ELSE 'C'
    END AS foo
FROM product p
ORDER BY foo;

(运行良好)

SELECT 
CASE WHEN description LIKE '%a%' THEN 'A'
        WHEN description LIKE '%b%' THEN 'B'
        ELSE 'C'
    END AS foo
FROM product p
ORDER BY FIELD(foo, 'A', 'B', 'C');    -- Different line

(错误)

如果您想按别名分组,请将您的查询放入派生的 table

SELECT foo, count(*) cnt FROM (
    SELECT 
    CASE WHEN description LIKE '%a%' THEN 'A'
        WHEN description LIKE '%b%' THEN 'B'
        ELSE 'C'
    END AS foo
    FROM product p
) t1
GROUP BY foo
ORDER BY FIELD(foo, 'A', 'B', 'C');    -- Different line

您的错误发生是因为您不能在 field 方法中使用别名。

使用 1 而不是 foo。像这样:

ORDER BY FIELD(1, 'A', 'B', 'C');    -- Different line

如果您知道顺序位置,您应该能够按顺序分组,例如..

select *
   from
      ( SELECT 
              CASE WHEN description LIKE '%a%' THEN 'A'
                   WHEN description LIKE '%b%' THEN 'B'
                   ELSE 'C' END AS foo
              ,COUNT(*) AS cnt
           FROM product p
           GROUP BY 1 ) PreQuery
   ORDER BY 
      FIELD(foo, 'A', 'B', 'C');

我知道 order by 可能不起作用,因为它是函数的一部分,所以我将其包装了......或者,您只需要让动态构造的查询构建 case/when 条件,然后将它粘贴到每个组件中

SELECT 
      CASE WHEN description LIKE '%a%' THEN 'A'
           WHEN description LIKE '%b%' THEN 'B'
           ELSE 'C' END AS foo
      ,COUNT(*) AS cnt
   FROM 
      product p
   GROUP BY 
      CASE WHEN description LIKE '%a%' THEN 'A'
           WHEN description LIKE '%b%' THEN 'B'
           ELSE 'C' END
   ORDER BY 
      FIELD( CASE WHEN description LIKE '%a%' THEN 'A'
                  WHEN description LIKE '%b%' THEN 'B'
                  ELSE 'C' END, 'A', 'B', 'C');

发生这种情况的原因是因为 MySQL 在早期版本(显然包括 5.0)中处理 ORDER BY 的方式如下:

  1. 如果整个ORDER BY子句是整数,则按projection子句对应的元素排序(ORDER BY 2按project子句的第二个元素排序)

  2. 如果整个 ORDER BY 子句是标识符,则搜索具有此类别名的投影列表元素,或者,如果 none 找到,则搜索具有此类别名的列名称,并以此排序。

  3. 否则,解析表达式。解析过程中只有列名可见,别名不可见。

所以在你的第一个查询中你得到了第二种情况,因此你看到了别名,在你的第二个查询中你得到了第三种情况,因此看不到它。

更新:似乎 PostgreSQL 具有完全相同的行为。在这里查看 Peter Eisentraut 的回答 [ ORDER BY Alias not working ]

他总结了我所说的相同内容,但针对的是 PostgreSQL。 Order By 可以有一个别名(输出列),或者一个整数,或者一个引用输入列.

的表达式