在子查询和别名中排序
Posted
技术标签:
【中文标题】在子查询和别名中排序【英文标题】:Order by in subquery and alias 【发布时间】:2019-09-25 08:11:31 【问题描述】:我在 oracle 查询中的 order by 有问题。
select KEY, B, C, (select D from TABLE1 a where a.KEY = b.KEY and a.DATE<
b.DATE order BY a.DATE and rownum =1 )
FROMSTATUS from TABLE2 b
我知道“order by”在子查询中不起作用。我将查询修改为:
select KEY, B, C, (select * from (select D from TABLE1 a where a.KEY =
b.KEY and a.DATE< b.DATE order by DATE) where rownum = 1)
FROMSTATUS from TABLE2 b
但是通过这种方式 B.KEY 和 B.DATE 并没有被 oracle 解析
我只需要从 TABLE2 中选择一个 1 值,该值是前一个 a.DATE
例子:
TABLE1
KEY DATE A B C
1 01/31/2000 1 2 3
2 02/25/2000 X Y Z
TABLE2
KEY DATE D
1 01/30/2000 1
1 01/27/2000 2
1 01/25/2000 2
2 02/20/2000 4
2 02/13/2000 1
我需要这个结果:
TABLE1.KEY TABLE1.DATE TABLE1.A TABLE1.B TABLE1.C TABLE2.DATE TABLE2.D
1 01/31/2000 1 2 3 01/30/2000 1
2 02/25/2000 X Y Z 02/20/2000 4
你能帮帮我吗?
(对不起我的英语不好)
【问题讨论】:
跳过子查询,改为执行 LEFT JOIN。 查询与您的描述不符。您已将 table1 和 table2 混合在一起。您还应用了错误的顺序,它必须是order by date desc
才能首先获得最高日期。
@ThorstenKettner 你有理由,我有正确的问题
【参考方案1】:
union
之后的row_number()
会得到你的输出。
select tFinal.DATE, tFinal.KEY
from (select row_number() over (partition by KEY order by t1.T, t1.DATE desc) as rn, t1.DATE, t1.KEY
from
(select DATE, KEY, 't1' as T from TABLE1
union all
select DATE, KEY, 't2' as T from TABLE2) t1) tFinal
Where rn = 2
【讨论】:
【参考方案2】:您可以为此使用窗口函数:
WITH cte AS (
SELECT TABLE2.KEY, TABLE2.B, TABLE2.C, TABLE1.D
, ROW_NUMBER() OVER (PARTITION BY TABLE2.KEY, TABLE2.DATE ORDER BY TABLE1.DATE DESC) AS rn
FROM TABLE2
LEFT JOIN TABLE1 ON TABLE2.KEY = TABLE1.KEY AND TABLE2.DATE > TABLE1.DATE
)
SELECT *
FROM cte
WHERE rn = 1
【讨论】:
【参考方案3】:这是一个使用聚合的答案:
WITH t1 AS (SELECT 1 KEY, to_date('31/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 2 KEY, to_date('25/02/2000', 'dd/mm/yyyy') dt FROM dual),
t2 AS (SELECT 1 KEY, to_date('30/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 1 KEY, to_date('27/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 1 KEY, to_date('25/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 2 KEY, to_date('20/02/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 2 KEY, to_date('13/02/2000', 'dd/mm/yyyy') dt FROM dual)
SELECT t1.KEY,
t1.dt t1_date,
MAX(t2.dt) t2_date
FROM t1
LEFT OUTER JOIN t2 ON t1.key = t2.key AND t2.dt < t1.dt
GROUP BY t1.key, t1.dt
ORDER BY t1.key;
KEY T1_DATE T2_DATE
---------- ----------- -----------
1 31/01/2000 30/01/2000
2 25/02/2000 20/02/2000
我在这里假设 t1.key 是一个唯一的列。这是否比您的数据的任何其他答案更具性能取决于您来测试 *:-)
【讨论】:
【参考方案4】:在 Oracle 中,您可以为此使用 KEEP LAST
:
select
key,
b,
c,
(
select max(d) keep (dense_rank last order by t2.date)
from table2 t2
where t2.key = t1.key and t2.date < t1.date
) as fromstatus
from table1 t1;
从 Oracle 12c 开始,您还可以使用 FETCH FIRST ROW
:
select
key,
b,
c,
(
select d
from table2 t2
where t2.key = t1.key and t2.date < t1.date
order by t2.date desc
fetch first row only
) as fromstatus
from table1 t1;
或者,将子查询移动到FROM
子句:
select
t1.key,
t1.b,
t1.c,
first_t2.d as fromstatus
from table1 t1
outer apply
(
select d
from table2 t2
where t2.key = t1.key and t2.date < t1.date
order by t2.date desc
fetch first row only
) first_t2;
最后一个查询的优点是您可以轻松地从 table2 行中选择更多值,而不仅仅是一个。
【讨论】:
以上是关于在子查询和别名中排序的主要内容,如果未能解决你的问题,请参考以下文章