2016-09-01 107 views
0

根據相同的條件,我的SQL有兩個結果字段。現在我必須寫兩遍。我想知道數據庫編譯器是否已經自動優化了代碼,或者如果我必須改變另一種方式來優化SQL?如何優化Oracle情況下的代碼情況?

select id,parent_id as p_Id,name, 
(case when exists(select * from t_group t2 where t1.id=t2.parent_id) 
then 2 else 1 end) type, 
(case when exists(select * from t_group t2 where t1.id=t2.parent_id) 
then 'true' else 'false' end) as is_Parent 
from t_group t1 

我試圖改變它是這樣的,但失敗了。

select id,parent_id as p_Id,name, 
(case when exists(select * from t_group t2 where t1.id=t2.parent_id) 
then 2 else 1 end) type, 
(case when type==1 
then 'true' else 'false' end) as is_Parent 
from t_group t1 

回答

1

使用一個公共表表達式或內嵌視圖,以獲得表達一次,然後使用它的是CTE或內嵌視圖之外。以下是我的意思是,使用內嵌視圖:

SELECT v.id, v.parent_id, v.name, v.type, case when v.type = 1 THEN 'TRUE' ELSE 'FALSE' END is_parent 
FROM 
(
select id,parent_id as p_Id,name, 
(case when exists(select * from t_group t2 where t1.id=t2.parent_id) 
then 2 else 1 end) type 
from t_group t1 
) v 
+0

您是否需要爲「內聯視圖」提供名稱?你會在很多系統中使用標準SQL,但Oracle可能不會。 –

+0

不,你不知道。但是,如果你想引用它的列並且有歧義,你會這樣做。我會更新我的答案。 –

0

我會使用LEFT JOIN以避免每行執行多個查詢重寫,同時確保加盟派生表左側不能超過一個返回行:

select t.id, 
     t.parent_id as p_id, 
     t.name, 
     case when c.parent_id is not null then 2 else 1 end as type, 
     case when c.parent_id is not null then 'true' else 'false' end as is_parent 
    from t_group t 
    left join (select parent_id, 
        row_number() over (partition by parent_id order by null) as rn 
       from t_group) c 
    on c.parent_id = t.id 
    and c.rn = 1 
+0

我不認爲這是最有效的方法。如果您擔心半連接是一個嵌套循環,您可以在公用表表達式中選擇「DISTINCT parent_id FROM t_group」,並將其與左連接。平均而言,我相信緩衝區會少一些。這種事情就是爲什麼Oracle需要半連接的顯式連接語法。 –

0
select id,parent_id as p_Id,name, 
     decode(t2.parent_id,NULL,1,2) type, 
     decode(t2.parent_id,NULL,'false','true') is_Parent 
    from t_group t1 
    left join(select distinct parent_id from t_group) t2 
    on t1.id=t2.parent_id 

如果存在於列PARENT_ID指數則優化器問題「索引範圍掃描」(如與在選擇一個子查詢)或「索引快速全掃描」(如果理解這是更快)。