首页 > 解决方案 > 有条件的 order by 子句

问题描述

下面的查询返回错误。帮我下错误和条件命令的实现方式。我试图在等级 >=8 时按等级和名称排序,当等级 <8 时按等级和分数排序。

SELECT
    name, grade, marks
FROM
    students, grades
WHERE
    min_mark <= marks
    AND   marks <= max_mark
    AND   marks >= 70
UNION
SELECT
    TO_CHAR('NULL') AS name, grade, marks
FROM
    students, grades
WHERE
    min_mark <= marks
    AND   marks <= max_mark
    AND   marks <= 69
order by grade desc,(case when grade >= 8 
                     then  name 
                     when grade < 8 
                     then marks  
                     end );

错误:
按等级排序,(等级> = 8时的情况
*
第18行的错误:
ORA-01785:ORDER BY项目必须是SELECT-list表达式的编号

标签: oraclejoinsql-order-byunion

解决方案


这似乎是错误 5695629,它似乎已针对 10g 提出,并且似乎尚未修复(截至 12cR2;我还没有 18 可玩),这是不寻常的。

您可以通过在订购前将查询包装在外部选择中来避免它:

select name, grade, marks
from
(
    SELECT
        name, grade, marks
    FROM
        students, grades
    WHERE
        min_mark <= marks
        AND   marks <= max_mark
        AND   marks >= 70
    UNION
    SELECT
        TO_CHAR('NULL') AS name, grade, marks
    FROM
        students, grades
    WHERE
        min_mark <= marks
        AND   marks <= max_mark
        AND   marks <= 69
)
order by grade desc,case when grade >= 1 
                     then  name 
                     when grade < 1 
                     then  marks
                     end ;

但是(可能)不同的数据类型 - 字符串namemarks数字 - 将会得到

ORA-00932: 不一致的数据类型: 预期的 CHAR 得到了 NUMBER

您可以转换marks为字符串,但如果这样做,则需要对其进行填充,以便按字母顺序对结果字符串进行排序仍然与数字顺序匹配 - 混乱但合理,因为标记可以(再次,大概 - 如果它是一个百分比?)只能向上三位数:

select name, grade, marks
from
(
    ...
    <the main part of your query here as a subquery, as above>
    ...
)
order by grade desc,case when grade >= 8 
                     then  name 
                     when grade < 8 
                     then  to_char(marks, 'FM000')
                     end ;

db<>fiddle 演示使用通过 CTE 提供的一些虚拟数据。

如果标记可以超过三位,则更改格式掩码以匹配最大可能长度。


TO_CHAR('NULL')部分也很奇怪,因为它会在这些行的名称列中为您提供文字字符串“NULL”。由于您从字符串文字开始,因此该TO_CHAR()部分毫无意义,请直接使用'NULL' AS name。如果您确实希望它为空白,那么您可以使用null AS name它,它将匹配联合的第一个分支中匹配列表达式的数据类型(并且也会选择它的别名)。您可以显式转换为字符串类型,例如,cast(null as varchar2(20)) AS name但似乎没有多大意义。


推荐阅读