2014-04-16 5 views
6

क्या कोई फ़ंक्शन या ऑपरेटर है या अन्यथा साधारण (आर) ऑरैकल एसक्यूएल में दो ट्यूपल अक्षरों के चौराहे को प्राप्त करने के लिए सरल है?ओरेकल एसक्यूएल: इंटरसेक्ट ट्यूपल लिटल

को ध्यान में निम्न उदाहरण ले रहा है:

निम्न तालिका

------------------------------ 
TABLE sometable 
------------------------------ 
id | telephone | mobile | fax 
------------------------------ 
1 | 123  | 456 | 789 

n संख्या {n1, एन 2, n3, ..., n} खोज आईडी की एक सूची को देखते हुए बीत रहा है , जैसे कि:

telephone = n1 or mobile = n1 or fax = n1 
or telephone = n2 or mobile = n2 or fax = n2 
or telephone = n3 or mobile = n3 or fax = n3 
.... 
or telephone = n or mobile = n or fax = n 

दो प्रशंसनीय समाधान हैं:

1. समाधान 1

SELECT id FROM sometable 
WHERE 
    n1 IN (telephone, mobile, fax) 
OR n2 IN (telephone, mobile, fax) 
OR n3 IN (telephone, mobile, fax) 
.... 
OR n IN (telephone, mobile, fax) 
; 

2. समाधान 2

SELECT id FROM sometable 
WHERE 
    telephone IN (n1, n2, n3, ..., n) 
OR mobile IN (n1, n2, n3, ..., n) 
OR fax  IN (n1, n2, n3, ..., n) 
; 

लेकिन वहाँ एक समारोह/ऑपरेटर निम्न करने के लिए है?

SELECT id 
FROM sometable 
WHERE 
intersect_function 
(
    (telephone, mobile, fax), 
    (n1, n2, n3, ..., n) 
) 
= TRUE 
; 

एक वैकल्पिक, सरल निर्माण का स्वागत किया जा सकता है, को ध्यान में ले जा रहा है कि इस हालत अधिक संख्या में और संभवतः अधिक जटिल परिस्थितियों के साथ एक लंबे समय तक क्वेरी का हिस्सा है।

धन्यवाद।

फिर एक छोटे से regexp चाल आप बना सकते हैं के साथ, एक ही पंक्ति से, प्रति मान एक पंक्ति है, और उन्हें अपनी मेज के खिलाफ मेल खाते हैं:

उत्तर

2

मेरा विचार आपके खोज संख्या एक तालिका में with खंड के माध्यम से कन्वर्ट करने के लिए है in खंड के लिए धन्यवाद:

create TABLE sometable 
(
    id number, 
    telephone number, 
    mobile number, 
    fax number 
); 

insert into sometable values(1, 123, 456, 789); 
insert into sometable values(2, 0, 0, 123); 
insert into sometable values(3, 456, 0, 0); 

with w(n) as 
(
    select regexp_substr('123, 456', '\d+', 1, level) n 
    from dual 
    connect by regexp_instr('123, 456', '\d+', 1, level) != 0 
) 
select * 
from sometable s, w 
where w.n in (s.telephone, s.mobile, s.fax) 
; 

इस रूप में की उम्मीद देता है:

ID TELEPHONE MOBILE FAX N 
1 123  456  789 123 
2 0   0  123 123 
1 123  456  789 456 
3 456  0  0 456 
+0

'चयन regexp_substr ('123, 456', '\ d +', 1, स्तर) n दोहरी से regexp_instr से कनेक्ट ('123, 456', '\ d +', 1, स्तर)! = 0' बहुत उपयोगी है। एक बार जब आप इसे एक टेबल में तोड़ते हैं तो संभावनाएं असंख्य होती हैं। मैंने देखा है कि एक दिलचस्प बात यह है कि क्वेरी की लागत तय होती है जबकि समाधान 1 और 2 लागत समान होती है और भिन्न होती है। – fluxy

1

अपने स्वयं के प्रकार और समारोह बना कर इस समारोह

SQL> create type num_tab is table of number; 
    2/

Type created. 

... और:: यदि आप इस प्रकार की घोषणा करने की जरूरत है

SELECT id 
FROM sometable 
WHERE 
intersect_function 
(
    num_tab(telephone, mobile, fax), 
    num_tab(123, 456) 
) > 0; 

पहले: तुम बहुत अपने वांछित एसक्यूएल करने के लिए कुछ इसी तरह प्राप्त कर सकते हैं

create or replace function intersect_function 
    (p_tab1 num_tab 
    , p_tab2 num_tab 
) return number 
is 
    l_intersect num_tab; 
begin 
    l_intersect := p_tab1 multiset intersect p_tab2; 
    return l_intersect.count; 
end; 

हालांकि, हो सकता है जानते हैं कि डेटा की प्रत्येक पंक्ति के लिए एक फ़ंक्शन को कॉल करके और इंडेक्स का उपयोग करने में सक्षम होने के बिना यह सबसे अधिक प्रदर्शन समाधान नहीं हो सकता है!

+0

यह डेटा को टेबल में तोड़ने का भी एक शानदार तरीका है। हालांकि मेरी प्राथमिकता @Emmanuel द्वारा सुझाई गई तकनीक पर जाती है क्योंकि यह कस्टम प्रकार बनाने और बेहतर प्रदर्शन करने की आवश्यकता से बचाती है। – fluxy

+0

हां, @ Emmanuel के समाधान के साथ जाने के दो अच्छे कारण हैं। –

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