我正在尝试在Oracle SQL中运行子查询,它不会让我订购子查询列。对子查询进行排序非常重要,因为Oracle似乎随意选择返回哪一列返回主查询。
select ps.id, ps.created_date, pst.last_updated, pst.from_state, pst.to_state,
(select last_updated from mwcrm.process_state_transition subpst
where subpst.last_updated > pst.last_updated
and subpst.process_state = ps.id
and rownum = 1) as next_response
from mwcrm.process_state ps, mwcrm.process_state_transition pst
where ps.created_date > sysdate - 1/24
and ps.id=pst.process_state
order by ps.id asc
真的应该是:
select ps.id, ps.created_date, pst.last_updated, pst.from_state, pst.to_state,
(select last_updated from mwcrm.process_state_transition subpst
where subpst.last_updated > pst.last_updated
and subpst.process_state = ps.id
and rownum = 1
order by subpst.last_updated asc) as next_response
from mwcrm.process_state ps, mwcrm.process_state_transition pst
where ps.created_date > sysdate - 1/24
and ps.id=pst.process_state
order by ps.id asc
答案 0 :(得分:21)
实际上“排序”只对最外层的查询有意义 - 如果您在子查询中进行排序,则允许外部查询随意对结果进行加扰,因此子查询排序基本上没有任何内容。
看起来你只想获得大于pst.last_updated的最小last_updated - 当你把它看作最小值(聚合)时,它会更容易,而不是第一行(这带来了其他问题,就像为next_response绑定了两行一样?)
给它一个机会。公平的警告,自从我在我面前使用Oracle几年后,我不习惯子查询作为列的语法;如果爆炸了,我会在from子句中用它制作一个版本。
select
ps.id, ps.created_date, pst.last_updated, pst.from_state, pst.to_state,
( select min(last_updated)
from mwcrm.process_state_transition subpst
where subpst.last_updated > pst.last_updated
and subpst.process_state = ps.id) as next_response
from <the rest>
答案 1 :(得分:16)
dcw和Dems都提供了适当的替代查询。我只是想解释为什么你的查询没有按照你期望的方式运行。
如果您的查询包含ROWNUM和ORDER BY,Oracle首先应用ROWNUM,然后应用ORDER BY。所以查询
SELECT *
FROM emp
WHERE rownum <= 5
ORDER BY empno
从EMP
表中获取任意5行并对其进行排序 - 几乎肯定不是预期的。如果要使用ROWNUM获取“前N行”,则需要嵌套查询。此查询
SELECT *
FROM (SELECT *
FROM emp
ORDER BY empno)
WHERE rownum <= 5
对EMP表中的行进行排序并返回前5个。
答案 2 :(得分:8)
我自己也经历过这种情况,你必须使用ROW_NUMBER()和一个额外级别的子查询,而不是rownum ......
只显示新的子查询,类似于......
(
SELECT
last_updated
FROM
(
select
last_updated,
ROW_NUMBER() OVER (ORDER BY last_updated ASC) row_id
from
mwcrm.process_state_transition subpst
where
subpst.last_updated > pst.last_updated
and subpst.process_state = ps.id
)
as ordered_results
WHERE
row_id = 1
)
as next_response
另一种方法是使用MIN代替......
(
select
MIN(last_updated)
from
mwcrm.process_state_transition subpst
where
subpst.last_updated > pst.last_updated
and subpst.process_state = ps.id
)
as next_response
答案 3 :(得分:1)
确认的答案是完全错误的。
考虑一个生成唯一行索引号的子查询。
例如,Oracle中的ROWNUM
。
您需要子查询来创建用于分页目的的唯一记录号(见下文)。
考虑以下示例查询:
SELECT T0.*, T1.* FROM T0 LEFT JOIN T1 ON T0.Id = T1.Id
JOIN
(
SELECT DISTINCT T0.*, ROWNUM FROM T0 LEFT JOIN T1 ON T0.Id = T1.Id
WHERE (filter...)
)
WHERE (filter...) AND (ROWNUM > 10 AND ROWNUM < 20)
ORDER BY T1.Name DESC
内部查询是完全相同的查询,但在T0上是DISTINCT
。
您无法将ROWNUM
放在外部查询上,因为LEFT JOIN
(s)可能会产生更多结果。
如果您可以订购内部查询(T1.Name DESC
),则内部查询中生成的ROWNUM
将匹配。
由于您不能在子查询中使用ORDER B
Y,因此数字不匹配且无用。
感谢上帝解决此问题的ROW_NUMBER OVER (ORDER BY ...)
。
虽然并非所有数据库引擎都支持。
两种方法中的一种,LIMIT
(不需要ORDER
)和ROW_NUMBER() OVER
将覆盖大多数数据库引擎。
但是,如果您没有其中一个选项,例如ROWNUM
是您唯一的选项,那么子查询上的ORDER BY
是必须的!