2010-06-23 14 views
5

यह एक नौसिखिया सवाल हो सकता है, लेकिन अभी भी ..ऑरैकल डीकोड के लिए लुकअप टेबल?

हम सभी Oracle की डीकोड और मामलों, उदा से परिचित हैं

select 
    decode (state, 
      0, 'initial', 
      1, 'current', 
      2, 'finnal', 
      state) 
from states_table 

या सीएएसई का उपयोग कर एक ही तरह की चीज।

अब मान लीजिए कि मैं ये वही मूल्यों के साथ एक मेज डालते हैं:

state_num | state_desc 
     0 | 'initial' 
     1 | 'current' 
     2 | 'finnal' 

वहाँ एक रास्ता मुझे लगता है कि डिकोड के लिए एक संसाधन के रूप में इस तालिका का उपयोग कर एक ही क्वेरी कर सकता है? कृपया ध्यान दें कि मैं अन्य तालिका का डेटा एक्सेस करने संयुक्त तालिका नहीं करना चाहता ... मैं बस वहाँ कुछ मैं decode(myField, usingThisLookupTable, thisValueForDefault) का एक तरह करने के लिए इस्तेमाल कर सकते हैं अगर जानना चाहते हैं।

उत्तर

3
बजाय एक में शामिल होने की

, आप एक सबक्वेरी है, यानी

select nvl(
    (select state_desc 
    from lookup 
    where state_num=state),to_char(state)) 
from states_table; 
+0

सच है, यह संभव है। लेकिन सलाह नहीं है। मैं अपना जवाब फिर से लिखूंगा हालांकि :-) –

+0

यह बस ऐसा करेगा। मैं इस अभ्यास के व्यापार से बहुत परिचित नहीं हूं, लेकिन यदि एक छोटी सी क्वेरी के साथ मैं एक बड़े पैमाने पर डीकोड कर रहा हूं तो यह बहुत गन्दा हो जाएगा :(@ammoQ, क्या आपके पास डिफ़ॉल्ट मान के लिए कोई सुझाव होगा? चीयर्स! – filippo

+0

संपादित करें : एक डिफ़ॉल्ट मान –

2

नहीं, आपकी दूसरी तालिका में शामिल होने के अलावा, कोई अन्य तरीका नहीं है। निश्चित रूप से, आप अपने चुने हुए खंड में एक स्केलर सबक्वायरी लिख सकते हैं, या आप अपना खुद का फ़ंक्शन लिख सकते हैं, लेकिन यह अक्षम अभ्यास होगा।

आप तालिका से डेटा की जरूरत है, तो आप इसे से चयन करने की जरूरत है।

संपादित करें: मुझे अक्षम अभ्यास के बारे में अपने पहले के बयान को परिष्कृत करना होगा।

अपनी चुनी सूची में स्केलर सबक्वायरी का उपयोग करते समय, आप उम्मीद करेंगे कि आप नेस्टेड-लूप लुक-ए-जैसी योजना को मजबूर कर रहे हैं, जहां स्केलर सबक्वायरी राज्य_टेबल की प्रत्येक पंक्ति के लिए निष्पादित हो जाती है। कम से कम मुझे उम्मीद थी कि :-)।

हालांकि, ओरेकल ने स्केलर सबक्वायरी कैशिंग को कार्यान्वित किया है, जो वास्तव में एक अच्छा अनुकूलन की ओर जाता है। यह केवल subquery 3 बार निष्पादित करता है। स्केलर सबक्वायरीज़ के बारे में एक उत्कृष्ट लेख है जहां आप देख सकते हैं कि इस अनुकूलन में कैसा व्यवहार होता है: http://www.oratechinfo.co.uk/scalar_subqueries.html#scalar3

यह काम पर देखने के लिए मेरा स्वयं का परीक्षण है।

create table states_table (id,state,filler) 
as 
select level 
     , floor(dbms_random.value(0,3)) 
     , lpad('*',1000,'*') 
    from dual 
connect by level <= 100000 
/
alter table states_table add primary key (id) 
/
create table lookup_table (state_num,state_desc) 
as 
select 0, 'initial' from dual union all 
select 1, 'current' from dual union all 
select 2, 'final' from dual 
/
alter table lookup_table add primary key (state_num) 
/
alter table states_table add foreign key (state) references lookup_table(state_num) 
/
exec dbms_stats.gather_table_stats(user,'states_table',cascade=>true) 
exec dbms_stats.gather_table_stats(user,'lookup_table',cascade=>true) 

फिर क्वेरी निष्पादित और वास्तविक कार्य योजना लागू करके पर एक नजर है:

SQL> select /*+ gather_plan_statistics */ 
    2   s.id 
    3  , s.state 
    4  , l.state_desc 
    5 from states_table s 
    6   join lookup_table l on s.state = l.state_num 
    7/

     ID  STATE STATE_D 
---------- ---------- ------- 
     1   2 final 
... 
    100000   0 initial 

100000 rows selected. 

SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last')) 
    2/

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------------------------------------------------------------- 
SQL_ID f6p6ku8g8k95w, child number 0 
------------------------------------- 
select /*+ gather_plan_statistics */  s.id  , s.state  , l.state_desc from states_table s  join 
lookup_table l on s.state = l.state_num 

Plan hash value: 1348290364 

--------------------------------------------------------------------------------------------------------------------------------- 
| Id | Operation   | Name   | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | 
--------------------------------------------------------------------------------------------------------------------------------- 
|* 1 | HASH JOIN   |    |  1 | 99614 | 100K|00:00:00.50 | 20015 | 7478 | 1179K| 1179K| 578K (0)| 
| 2 | TABLE ACCESS FULL| LOOKUP_TABLE |  1 |  3 |  3 |00:00:00.01 |  3 |  0 |  |  |   | 
| 3 | TABLE ACCESS FULL| STATES_TABLE |  1 | 99614 | 100K|00:00:00.30 | 20012 | 7478 |  |  |   | 
--------------------------------------------------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - access("S"."STATE"="L"."STATE_NUM") 


20 rows selected. 

अब अदिश सबक्वेरी संस्करण के लिए भी ऐसा ही करने के लिए अपने टेबल के अनुकरण के लिए, मैं इस स्क्रिप्ट प्रयोग किया है:

SQL> select /*+ gather_plan_statistics */ 
    2   s.id 
    3  , s.state 
    4  , (select l.state_desc 
    5    from lookup_table l 
    6   where l.state_num = s.state 
    7  ) 
    8 from states_table s 
    9/

     ID  STATE (SELECT 
---------- ---------- ------- 
     1   2 final 
... 
    100000   0 initial 

100000 rows selected. 

SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last')) 
    2/

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------------------------------------------------------------- 
SQL_ID 22y3dxukrqysh, child number 0 
------------------------------------- 
select /*+ gather_plan_statistics */  s.id  , s.state  , (select l.state_desc 
from lookup_table l   where l.state_num = s.state  ) from states_table s 

Plan hash value: 2600781440 

--------------------------------------------------------------------------------------------------------------- 
| Id | Operation     | Name   | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | 
--------------------------------------------------------------------------------------------------------------- 
| 1 | TABLE ACCESS BY INDEX ROWID| LOOKUP_TABLE |  3 |  1 |  3 |00:00:00.01 |  5 |  0 | 
|* 2 | INDEX UNIQUE SCAN   | SYS_C0040786 |  3 |  1 |  3 |00:00:00.01 |  2 |  0 | 
| 3 | TABLE ACCESS FULL   | STATES_TABLE |  1 | 99614 | 100K|00:00:00.30 | 20012 | 9367 | 
--------------------------------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - access("L"."STATE_NUM"=:B1) 


20 rows selected. 

और चरण 1 और 2 के स्टार्ट कॉलम को देखें: केवल 3!

इस अनुकूलन हमेशा अपनी स्थिति में एक अच्छी बात है या नहीं, कई कारकों पर निर्भर करता है। आप कुछ के प्रभाव को देखने के लिए पहले उल्लिखित आलेख को देख सकते हैं।

केवल तीन राज्यों के साथ अपनी स्थिति में, ऐसा लगता है जैसे आप अदिश सबक्वेरी संस्करण के साथ गलत नहीं जा सकते लग रहा है।

सम्मान, रॉब।

+0

हाँ दोस्त इस्तेमाल कर सकते हैं ..मैं वही नहीं चाहता जैसा कि मैंने रेखांकित किया है "कृपया ध्यान दें कि मैं तालिका को अन्य तालिका से डेटा तक पहुंचने के लिए जोड़ना नहीं चाहता हूं ..." स्थिति यह है कि मैं एक प्रणाली में फंस गया हूं जो मुझे अनुमति देगा प्रत्येक फ़ील्ड के लिए पैरामीटर दर्ज करने के लिए, लेकिन मुझे बाकी की क्वेरी को संपादित करने नहीं देगा। यही कारण है कि मैं एक डिकोड का उपयोग कर सकता हूं, लेकिन शामिल होने का उपयोग नहीं कर सकता। – filippo

+0

मैंने अपना जवाब संपादित किया क्योंकि मैंने बहुत जल्दी पढ़ना बंद कर दिया था। "अक्षम अभ्यास" के लिए –

+0

-1। अभ्यास में ओवरहेड कोड को समझने के खिलाफ ट्रेड-ऑफ के बहुत छोटे और अच्छी तरह से मूल्यवान है - जो एक बड़ा लाभ है। संबंधपरक डेटाबेस में enum समर्थन के बारे में काफी चर्चा हुई है - सूचित, और त्रुटिपूर्ण चर्चाओं के मिश्रण के लिए Google का प्रयास करें। – symcbean

संबंधित मुद्दे