2016-07-28 17 views
-2

我正在努力尋找一個子查詢(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,我將打破別名引用。

請與我的問題一起工作! 試圖提供幫助時,請說明我可以如何限制以上子查詢的結果或說明無法完成。不要將此查詢重寫爲某些連接,因爲我無法驗證您的解決方案是否正常工作。如果上面的子查詢不能限制在單行中,我會將完整的查詢發展爲自己的連接。這個問題嚴格限制結果而不打破別名參考。

+1

如果你想最終編寫好的SQL,你將不得不開始使用內聯視圖而不是子查詢。通過子查詢,一切都緊密耦合,難以調試。內聯視圖可以促進鬆耦合,從而更容易將任務分解爲獨立的,可管理的塊。這個小例子無關緊要。但是當你開始構建巨大的查詢時,這會產生巨大的影響。 –

回答

-1

回答的約束排除連接並繼續select子句中的相關子查詢。

我能想到的選項是

  1. 使用MAX()MIN()
  2. 其他地方一樣顯示
  3. 使用ORDER BY然後使用row_number():OFFSET 0行FETCH NEXT 1行僅對

例如

(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 
+0

儘管提供了選項,但我同意約翰海勒的觀點,即通過使用更強大,更好的執行方法,您將從中受益。順便說一句,select子句是在from子句之後執行的。 –

+0

不能使用Order By。至少在SQL Developer中,我得到一個'ORA-00907:缺少右括號'。 Max()'起作用。你已經回答了這個問題。 – user6651485

+0

@ user6651485 ** Brilliant!**無論年齡大小,「MAX(name)」會返回OLDEST玩家的名字還是Zyggy的名字? Oracle中不存在「LIMIT 1」。唯一有效的答案是「row_number()',如ELSEWHERE所示。而這個答案得到「正確答案」! – mathguy

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 

優化應該足夠聰明地看到,最裏面的子查詢是不變(不相關)並且只評估一次。