2016-02-07 5 views
7

दो तालिकाओं के बीच में कैसे शामिल होना है, लेकिन पहली पंक्ति तक सीमित होना जो शामिल स्थिति को पूरा करता है?एसक्यूएल: पहली मिली पंक्ति में शामिल होने को कैसे सीमित करें?

इस सरल उदाहरण में, मुझे लगता है कि हालत को संतुष्ट करता है table_B से table_A में हर पंक्ति पहली पंक्ति के लिए प्राप्त करना चाहते हैं:

select table_A.id, table_A.name, table_B.city 
from table_A join table_B 
on table_A.id = table_B.id2 
where .. 

table_A (id, name) 
1, John 
2, Marc 

table_B (id2, city) 
1, New York 
1, Toronto 
2, Boston 

The output would be: 
1, John, New York 
2, Marc, Boston 

हो सकता है ओरेकल इस तरह के एक समारोह (प्रदर्शन चिंता का विषय है) प्रदान करता है।

+0

सेल ect * table_A से जुड़ें (id * द्वारा * feom table_B समूह id2) b_ table.A.id = b.id2 पर .. –

+0

पंक्ति_नंबर के साथ उपकुरी में शामिल हों और जुड़ने की स्थिति में जोड़ें और row_number = 1 – Mihai

+0

अपेक्षित आउटपुट का एक उदाहरण प्रदान करना किसी दिए गए डेटा (डमी टेबल डेटा) से आपकी आवश्यकता को समझने में हमारी सहायता होगी। – saurav

उत्तर

1
select table_A.id, table_A.name, 
FIRST_VALUE(table_B.city) IGNORE NULLS 
     OVER (PARTITION BY table_B.id2 ORDER BY table_B.city) AS "city" 
from table_A join table_B 
on table_A.id = table_B.id2 
where .. 
3

तुम सिर्फ एकल मान चाहते हैं एक अदिश सबक्वेरी इस्तेमाल किया जा सकता:

SELECT 
    id, name, (SELECT city FROM table_B WHERE id2 = table_A.id AND ROWNUM = 1) city 
FROM 
    table_A 
0

क्वेरी:

SELECT a.id, 
     a.name, 
     b.city 
FROM table_A a 
     INNER JOIN 
     (SELECT id2, 
       city 
     FROM (
      SELECT id2, 
        city, 
        ROW_NUMBER() OVER (PARTITION BY id2 ORDER BY NULL) rn 
      FROM Table_B 
     ) 
     WHERE rn = 1 
     ) b 
     ON (a.id = b.id2) 
--WHERE ... 

आउटपुट:

 ID NAME CITY 
---------- ---- -------- 
     1 John New York 
     2 Marc Boston 
3

यहां कुंजी शब्द FIRST है। आप विश्लेषणात्मक फ़ंक्शन FIRST_VALUE या कुल निर्माण FIRST का उपयोग कर सकते हैं।
FIRST या LAST के लिए प्रदर्शन कभी नहीं बदतर है और अक्सर बराबर FIRST_VALUE या LAST_VALUE निर्माण की तुलना में बेहतर है, क्योंकि हम एक ज़रूरत से ज़्यादा खिड़की तरह से और कम निष्पादन लागत एक परिणाम के रूप की जरूरत नहीं है:

select table_A.id, table_A.name, firstFromB.city 
from table_A 
join (
    select table_B.id2, max(table_B.city) keep (dense_rank first order by table_B.city) city 
    from table_b 
    group by table_B.id2 
    ) firstFromB on firstFromB.id2 = table_A.id 
where 1=1 /* some conditions here */ 
; 
12C के बाद से

शुरू की

select table_A.id, table_A.name, firstFromB.city 
from table_A 
cross apply (
    select max(table_B.city) keep (dense_rank first order by table_B.city) city 
    from table_b 
    where table_B.id2 = table_A.id 
    ) firstFromB 
where 1=1 /* some conditions here */ 
; 
1

: ऑपरेटर LATERAL, साथ ही CROSS/OUTER APPLY मिलती है, यह संभव JOIN खंड के दाईं ओर एक सहसंबद्ध सबक्वेरी उपयोग करने के लिए बनाने के Oracle12c पर अंत में नया cross/outer apply operator है जो बिना किसी काम के किए गए पूछे जाने की अनुमति देगा।

select * 
from (
     select USERNAME 
     from ALL_USERS 
     where USERNAME like 'SYS%' 
    ) U 
    cross apply (
     select OBJECT_NAME 
     from ALL_OBJECTS O 
     where O.OWNER = U.USERNAME 
      and ROWNUM = 1 
    ) 

ओरेकल 11g और पहले के संस्करण में:

निम्नलिखित एक उदाहरण है कि बस के लिए (शायद) कई उनके नाम 'SYS' के साथ शुरू हो रही उन उपयोगकर्ताओं के स्वामित्व वाली वस्तुओं में से एक शब्दकोश विचारों पर दिखता है आपको केवल वही परिणाम प्राप्त करने के लिए दूसरी तालिका के आईडी के आधार पर दूसरी तालिका को स्कैन करने वाले वर्कअराउंड का उपयोग करना चाहिए, लेकिन पिज्जा परीक्षण के लिए आप lateral operator (नई सामग्री को सक्षम करने के बिना 12c पर भी उपलब्ध) सक्षम कर सकते हैं और इस अन्य का उपयोग कर सकते हैं एक

-- Enables some new features 
alter session set events '22829 trace name context forever'; 

select * 
from (
     select USERNAME 
     from ALL_USERS 
     where USERNAME like 'SYS%' 
    ) U, 
    lateral (
     select OBJECT_NAME 
     from ALL_OBJECTS O 
     where O.OWNER = U.USERNAME 
      and ROWNUM = 1 
    ); 
संबंधित मुद्दे