如何限制使用外部查询别名的相关子查询的结果?
How to limit results of a correlated subquery that uses outer query aliases?
我正在努力处理子查询 (Oracle 11)。出于问题的目的,下面的示例是 'invented' 。
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM PLAYER PL
WHERE PL.TMID=**TM.TMID**
ORDER BY AGE) AS OLDEST_PLAYER_NAME
FROM TEAM **TM**
同样,这是一个虚构的例子。我们不要讨论任何关于命名约定、规范化或年龄计算的问题。
手头的问题是相关查询 returns 多个结果,我需要选择第一个。如果我将该相关查询包装在另一个查询中以执行 select .... where rownum<=1
,我将破坏别名引用。
请回答我的问题!
尝试提供帮助时,请说明我如何限制上述子查询的结果或说明无法完成。不要将此查询重写为某些连接,因为我无法验证您的解决方案是否有效。如果上面的子查询不能局限于单行,我会自己将完整的查询演变成连接。这个问题严格来说是关于在不破坏别名引用的情况下限制结果。
这样的事情可能会奏效。您不需要相关的子查询,您需要与正确定义的子查询的连接。
从那以后就没有测试过(好吧,你知道其余的)。
select tm.tmid as team_id, x.first_name || ' ' || x.last_name as oldest_player_name
from team tm
inner join
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) as rn
from player) x
on tm.tmid = x.tmid
where rn = 1;
已编辑:如果您出于某种原因必须使用相关子查询,您可以这样做:
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) rn
from PLAYER
) PL
WHERE PL.TMID=TM.TMID
AND rn = 1) AS OLDEST_PLAYER_NAME
FROM TEAM TM
优化器应该足够聪明,可以看到最里面的子查询是常量(不相关)并且只评估一次。
回答排除连接的约束并继续 select 子句中的相关子查询。
我能想到的方案有
- 使用
MAX()
或MIN()
- 如其他地方所示使用
row_number ()
- 然后使用 ORDER BY:OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
例如
( Select MAX(name) from tablex x
where x.id = outer.id )
对于 1 的限制,您可以执行以下操作:
select
customer_id
, (select cust_last_name
from demo_customers c
where c.customer_id = o.customer_id
ORDER BY c.cust_state desc
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
) name
from demo_orders o
但是:在该示例中,没有充分的理由不使用效率更高的联接。
select
o.customer_id
, c.cust_last_name
from demo_orders o
inner join demo_customers c
on c.customer_id = o.customer_id
我正在努力处理子查询 (Oracle 11)。出于问题的目的,下面的示例是 'invented' 。
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM PLAYER PL
WHERE PL.TMID=**TM.TMID**
ORDER BY AGE) AS OLDEST_PLAYER_NAME
FROM TEAM **TM**
同样,这是一个虚构的例子。我们不要讨论任何关于命名约定、规范化或年龄计算的问题。
手头的问题是相关查询 returns 多个结果,我需要选择第一个。如果我将该相关查询包装在另一个查询中以执行 select .... where rownum<=1
,我将破坏别名引用。
请回答我的问题! 尝试提供帮助时,请说明我如何限制上述子查询的结果或说明无法完成。不要将此查询重写为某些连接,因为我无法验证您的解决方案是否有效。如果上面的子查询不能局限于单行,我会自己将完整的查询演变成连接。这个问题严格来说是关于在不破坏别名引用的情况下限制结果。
这样的事情可能会奏效。您不需要相关的子查询,您需要与正确定义的子查询的连接。
从那以后就没有测试过(好吧,你知道其余的)。
select tm.tmid as team_id, x.first_name || ' ' || x.last_name as oldest_player_name
from team tm
inner join
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) as rn
from player) x
on tm.tmid = x.tmid
where rn = 1;
已编辑:如果您出于某种原因必须使用相关子查询,您可以这样做:
SELECT TM.TMID AS TEAM_ID
,(SELECT FIRST_NAME || ' ' || LAST_NAME
FROM
(select first_name, last_name, tmid,
row_number() over (partition by tmid order by age desc) rn
from PLAYER
) PL
WHERE PL.TMID=TM.TMID
AND rn = 1) AS OLDEST_PLAYER_NAME
FROM TEAM TM
优化器应该足够聪明,可以看到最里面的子查询是常量(不相关)并且只评估一次。
回答排除连接的约束并继续 select 子句中的相关子查询。
我能想到的方案有
- 使用
MAX()
或MIN()
- 如其他地方所示使用
row_number ()
- 然后使用 ORDER BY:OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
例如
( Select MAX(name) from tablex x
where x.id = outer.id )
对于 1 的限制,您可以执行以下操作:
select
customer_id
, (select cust_last_name
from demo_customers c
where c.customer_id = o.customer_id
ORDER BY c.cust_state desc
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
) name
from demo_orders o
但是:在该示例中,没有充分的理由不使用效率更高的联接。
select
o.customer_id
, c.cust_last_name
from demo_orders o
inner join demo_customers c
on c.customer_id = o.customer_id