Can';t在mysql函数中使用别名作为ORDERBY子句的一部分

Can';t在mysql函数中使用别名作为ORDERBY子句的一部分,mysql,sql,sql-order-by,Mysql,Sql,Sql Order By,如果我执行下面的查询,它就可以正常工作 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

如果我执行下面的查询,它就可以正常工作

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错误(1054):“order子句”中的未知列“foo”

为什么呢

我正在考虑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;
(运行良好)

vs


(错误)

如果要按别名分组,请将查询放入派生表中

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

发生错误的原因是无法在
字段中使用别名

使用
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的方式如下:

  • 如果整个
    orderby
    子句是一个整数,则按投影子句的相应元素排序(
    orderby 2
    按项目子句的第二个元素排序)

  • 如果整个
    ORDER BY
    子句是一个标识符,则搜索具有此类别名的投影列表元素,如果未找到,则搜索具有此类名称的列,并按其排序

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

  • 因此,在第一次查询中,您将看到第二种情况,因此您可以看到别名;在第二次查询中,您将看到第三种情况,因此您无法看到别名

    更新:似乎PostgreSQL具有完全相同的行为。请看彼得·艾森特的回答 []


    他总结了和我说的一样的东西,只是为了PostgreSQL。Order By可以有别名(输出列),也可以是整数,或者是引用输入列的表达式

    我知道这种可能性,但所讨论的查询(比我发布的示例更复杂)是通过友好方式生成的,因此,我不能像那样改变它的结构,而不对生成它的代码进行大量工作。在这种情况下,
    1
    当然是一个整数1,而不是投影的第一个元素。我可以在MySQL 5.6中运行精确的查询。您使用的是什么版本的MySQL?谢谢!在MySQL文档中,我找不到任何地方有明确的声明。我知道这一点,因为我以前玩过MySQL代码,并在其中看到了这种行为。
    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');