如何限制使用外部查询别名的相关子查询的结果?

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 子句中的相关子查询。

我能想到的方案有

  1. 使用MAX()MIN()
  2. 如其他地方所示使用row_number ()
  3. 然后使用 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