有条件的 order by 子句
Conditional order by clause
以下查询返回错误。帮我下错误和实现条件排序的方法。我试图在年级 >=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 );
ERROR:
order by grade desc,(case when grade >= 8
*
ERROR at line 18:
ORA-01785: ORDER BY item must be the number of a SELECT-list expression
SQL中CASE Expressions有2种形式。
CASE <expression> WHEN <v1> THEN <ret1> WHEN <v2> THEN <ret2> ... END
另一个是
CASE WHEN <comp1> THEN <ret1> WHEN <comp2> THEN <ret2> ... END
不同之处在于,在案例 1 中,您指定要比较一次的值或表达式并将其与其他值或表达式进行比较,而对于变体 2,您为每个 WHEN 指定一个比较表达式。
将表达式更改为
CASE WHEN grade >= 8 THEN name ELSE TO_CHAR(marks, '0999999999') END
我还将标记编号格式化为带有前导零的字符串,使其可以作为文本与名称一起排序。
这似乎是错误 5695629,它似乎已针对 10g 提出并且似乎尚未修复(截至 12cR2;我还没有 18 可以玩),这是不寻常的.
您可以通过在订购前将查询包装在外部 select 中来避免它:
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 ;
但由于 name
和 marks
是(大概)不同的数据类型 - 字符串和数字 - 而是会得到
ORA-00932: inconsistent datatypes: expected CHAR got 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 demo 使用一些通过 CTE 提供的虚拟数据。
如果标记可以超过三位数,则更改格式掩码以匹配可能的最大长度。
TO_CHAR('NULL')
部分也很奇怪,因为它将在这些行的名称列中为您提供文字字符串 "NULL"。由于您从字符串文字开始,因此 TO_CHAR()
部分毫无意义,只需直接使用 'NULL' AS name
即可。如果您真的希望它为空,那么您可以只使用 null AS name
,它将匹配联合的第一个分支中匹配列表达式的数据类型(并且也会选择它的别名)。您可以显式转换为字符串类型,例如cast(null as varchar2(20)) AS name
不过好像没什么意义
以下查询返回错误。帮我下错误和实现条件排序的方法。我试图在年级 >=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 );
ERROR:
order by grade desc,(case when grade >= 8
*
ERROR at line 18:
ORA-01785: ORDER BY item must be the number of a SELECT-list expression
SQL中CASE Expressions有2种形式。
CASE <expression> WHEN <v1> THEN <ret1> WHEN <v2> THEN <ret2> ... END
另一个是
CASE WHEN <comp1> THEN <ret1> WHEN <comp2> THEN <ret2> ... END
不同之处在于,在案例 1 中,您指定要比较一次的值或表达式并将其与其他值或表达式进行比较,而对于变体 2,您为每个 WHEN 指定一个比较表达式。
将表达式更改为
CASE WHEN grade >= 8 THEN name ELSE TO_CHAR(marks, '0999999999') END
我还将标记编号格式化为带有前导零的字符串,使其可以作为文本与名称一起排序。
这似乎是错误 5695629,它似乎已针对 10g 提出并且似乎尚未修复(截至 12cR2;我还没有 18 可以玩),这是不寻常的.
您可以通过在订购前将查询包装在外部 select 中来避免它:
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 ;
但由于 name
和 marks
是(大概)不同的数据类型 - 字符串和数字 - 而是会得到
ORA-00932: inconsistent datatypes: expected CHAR got 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 demo 使用一些通过 CTE 提供的虚拟数据。
如果标记可以超过三位数,则更改格式掩码以匹配可能的最大长度。
TO_CHAR('NULL')
部分也很奇怪,因为它将在这些行的名称列中为您提供文字字符串 "NULL"。由于您从字符串文字开始,因此 TO_CHAR()
部分毫无意义,只需直接使用 'NULL' AS name
即可。如果您真的希望它为空,那么您可以只使用 null AS name
,它将匹配联合的第一个分支中匹配列表达式的数据类型(并且也会选择它的别名)。您可以显式转换为字符串类型,例如cast(null as varchar2(20)) AS name
不过好像没什么意义