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

时间:2016-07-28 20:18:33

标签: sql oracle correlated-subquery

我正在努力使用子查询(Oracle 11)。下面的例子是发明的'出于问题的目的。

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**

同样,这是一个发明的例子。我们不讨论有关命名约定,规范化或年龄计算的任何讨论。

手头的问题是相关查询返回多个结果,我需要选择第一个结果。如果我将相关查询包装在另一个查询中以执行select .... where rownum<=1,我将打破别名引用。

请处理我的问题! 在尝试提供帮助时,请说明如何限制上面子查询的结果或声明无法完成。不要将此查询重写为某些联接,因为我无法验证您的解决方案是否有效。如果上面的子查询不能限于一行,我将自己完成查询到连接。这个问题严格来说是在不破坏别名参考的情况下限制结果。

2 个答案:

答案 0 :(得分:3)

这样的事可能有用。您不需要相关子查询,需要使用正确定义的子查询进行连接。

自从没有测试过(嗯,你知道其余的)。

    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

优化器应该足够智能,以便看到最里面的子查询是常量(不相关)并且只评估它一次。

答案 1 :(得分:-1)

对回答的约束排除了连接并继续使用select子句中的相关子查询。

我能想到的选项是

  1. 使用MAX()MIN()
  2. 使用row_number (),如其他地方所示
  3. 然后使用ORDER BY:OFFSET 0 ROWS FETCH NEXT 1 ROWS
  4. E.g

    ( 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