2012-04-27 13 views
9

मेरे तालिका:ओरेकल एसक्यूएल - एक समूह पर विश्लेषणात्मक कार्य?

ID NUM VAL 
1 1  Hello 
1 2  Goodbye 
2 2  Hey 
2 4  What's up? 
3 5  See you 

मैं प्रत्येक आईडी के लिए अधिकतम संख्या वापस जाने के लिए चाहते हैं, यह वास्तव में अच्छे और साफ है:

SELECT MAX(NUM) FROM table GROUP BY (ID) 

लेकिन क्या मैं अधिकतम के साथ जुड़े मूल्य हड़पने के लिए चाहते हैं, तो प्रत्येक आईडी के लिए प्रत्येक संख्या का?

मैं क्यों नहीं कर सकते हैं:

SELECT MAX(NUM) OVER (ORDER BY NUM) FROM table GROUP BY (ID) 

एक त्रुटि है कि क्यों है? मैं प्रत्येक विंडो के लिए अलग से विभाजित करने के बजाय आईडी द्वारा समूहित चयन करना चाहता हूं ...

संपादित करें: त्रुटि "अभिव्यक्ति द्वारा ग्रुप नहीं है"।

+1

हम यहाँ से अपने त्रुटि संदेश नहीं देख सकता। – RBarryYoung

+0

क्या आप जिस आउटपुट की अपेक्षा करते हैं उसे दिखा सकते हैं, विवरण मुझे समझ में नहीं आया ... 'मैं प्रत्येक आईडी के लिए प्रत्येक नंबर के अधिकतम से जुड़े मूल्य को पकड़ना चाहता हूं।' मुझे यह भी यकीन नहीं है कि एक ऑर्डर द्वारा MAX() फ़ंक्शन में क्या अंतर आएगा ... – MatBailie

+0

प्रश्न का सटीक उत्तर नहीं है लेकिन ऑरैकल विश्लेषणात्मक कार्यों के बारे में एक अच्छा परिचय [orafaq] (http: // www.orafaq.com/node/55)। पोस्ट सरल उदाहरणों के साथ अवधारणाओं को समझने में मदद करता है। –

उत्तर

13

आप शायद MAX() KEEP(DENSE_RANK LAST...) समारोह इस्तेमाल कर सकते हैं:

with sample_data as (
    select 1 id, 1 num, 'Hello' val from dual union all 
    select 1 id, 2 num, 'Goodbye' val from dual union all 
    select 2 id, 2 num, 'Hey' val from dual union all 
    select 2 id, 4 num, 'What''s up?' val from dual union all 
    select 3 id, 5 num, 'See you' val from dual) 
select id, max(num), max(val) keep (dense_rank last order by num) 
from sample_data 
group by id; 
+1

+1 वाह, यह उत्तर अच्छा है। क्या यह नहीं पता था कि विंडोिंग फ़ंक्शन पर कीप कार्यक्षमता है, या हो सकता है कि यह ओरेकल के स्वामित्व में हो, फिर भी यह सुरुचिपूर्ण समाधान है। यह उत्तर अधिकांश डेटाबेस पर काम करता है हालांकि http://stackoverflow.com/a/10359164 ओरेकल: http://www.sqlfiddle.com/#!4/a9a07/19 एसक्यूएल सर्वर: http://www.sqlfiddle.com/ #! 3/a9a07/1 Postgresql: http://www.sqlfiddle.com/#!1/a9a07/6 –

+0

मुझे प्यार है कि मैं ओरेकल के बारे में केवल एक प्रश्न के साथ प्रश्न कैसे प्राप्त करता हूं और शैतान क्या कर रहा है इसके बारे में कोई स्पष्टीकरण नहीं देता है और यह काम किस प्रकार करता है। अन्य परिस्थितियों के समाधान को लागू करने के लिए बहुत उपयोगी है। – jpmc26

3

आप पंक्तियों जो MAX(num) GROUP BY id से मान होते हैं, यह एक आम पैटर्न हो जाता है पाने के लिए देख रहे हैं ...

WITH 
    sequenced_data 
AS 
(
    SELECT 
    ROW_NUMBER() OVER (PARTITION BY id ORDER BY num DESC) AS sequence_id, 
    * 
    FROM 
    yourTable 
) 
SELECT 
    * 
FROM 
    sequenced_data 
WHERE 
    sequence_id = 1 


संपादित

मैं अगर Teradata इस अनुमति देगा पता नहीं है, लेकिन तर्क समझ बनाने के लिए लगता है ...

SELECT 
    * 
FROM 
    yourTable 
WHERE 
    num = MAX(num) OVER (PARTITION BY id) 

या हो सकता है ...

SELECT 
    * 
FROM 
(
    SELECT 
    *, 
    MAX(num) OVER (PARTITION BY id) AS max_num_by_id 
    FROM 
    yourTable 
) 
    AS sub_query 
WHERE 
    num = max_num_by_id 

यह वह जगह है मेरे पिछले उत्तर से थोड़ा अलग; यदि एकाधिक रिकॉर्ड एक ही MAX(num) से बंधे हैं, तो यह उन सभी को वापस कर देगा, दूसरा उत्तर केवल एक ही लौटाएगा।


संपादित

अपने प्रस्तावित एसक्यूएल में त्रुटि तथ्य यह है कि OVER() खंड एक क्षेत्र अपने ग्रुप द्वारा में नहीं होता है से संबंधित है। यह यह करने के लिए कोशिश की तरह क्योंकि वहाँ उस क्षेत्र में एक से अधिक मान हो सकता है के लिए प्रत्येक पंक्ति लौटे (साथ पंक्तियों से GROUP BY id परिभाषित किया जा रहा वापस लौटे) है ...

SELECT id, num FROM yourTable GROUP BY id 

num अमान्य है,।

इसी तरह, आप खंड के अंदर num नहीं डाल सकते हैं।

SELECT 

    id, 

    MAX(num),    <-- Valid as it is an aggregate 

    MAX(num)     <-- still valid 
    OVER(PARTITION BY id), <-- Also valid, as id is in the GROUP BY 

    MAX(num)     <-- still valid 
    OVER(PARTITION BY num) <-- Not valid, as num is not in the GROUP BY 

FROM 
    yourTable 
GROUP BY 
    id 


जब आप OVER() खंड में कुछ निर्दिष्ट नहीं कर सकते के लिए इस सवाल का, और दिखा जब (मुझे लगता है कि) एक जवाब देखें आप कर सकते हैं: over-partition-by-question

+1

[http://sqlfiddle.com] की एक त्वरित यात्रा (http://www.sqlfiddle.com/#!4/a9a07/23) यह सत्यापित कर सकती है कि यह काम नहीं करता है: 'आईडी का चयन करें, अपनेटेबल से वैल num = max (num) over (id द्वारा विभाजन) '। यह अच्छा होगा अगर यह काम करता है, बहुत संक्षिप्त –

4

जब आप का उपयोग विंडोिंग फ़ंक्शन, आपको अब ग्रुप बाय का उपयोग करने की आवश्यकता नहीं है, यह पर्याप्त होगा:

select id, 
    max(num) over(partition by id) 
from x 
select * 
from x 
where (id,num) in 
    (
    select id, max(num) 
    from x 
    group by id 
) 

आउटपुट::

ID NUM VAL 
1 2 Goodbye 
2 4 What's up 
3 5 SEE YOU 

http://www.sqlfiddle.com/#!4/a9a07/7


आप विंडोइंग समारोह का उपयोग करना चाहते हैं, तो आप यह कर सकता है:वास्तव में आप विंडोइंग समारोह का उपयोग किए बिना परिणाम प्राप्त कर सकते हैं

select id, val, 
    case when num = max(num) over(partition by id) then 
     1 
    else 
     0 
    end as to_select 
from x 
where to_select = 1 

या इस:

select id, val 
from x 
where num = max(num) over(partition by id) 

लेकिन क्योंकि यह उन करने की अनुमति नहीं है, तो आप ऐसा करने के लिए है:

with list as 
(
    select id, val, 
    case when num = max(num) over(partition by id) then 
     1 
    else 
     0 
    end as to_select 
    from x 
) 
select * 
from list 
where to_select = 1 

http://www.sqlfiddle.com/#!4/a9a07/19

+0

'ऑर्डर द्वारा ऑर्डर 'क्या प्राप्त करता है? '1,2,3' '' MAX() '' 2,3,1' '' MAX() 'के समान है ...' MAX() 'के लिए, निश्चित रूप से केवल' पक्ष द्वारा 'समझ में आता है? – MatBailie

+1

हां यह सच है, केवल MAX पर MAX को समझ में आता है। मेरे उत्तर पर पहला कोड (अधिकतम आदेश द्वारा आदेश) कोड ओपी के प्रश्न से तुरंत कॉपी-पेस्ट किया गया था। विंडोिंग फ़ंक्शन पर ऑर्डर केवल कुल चलने पर ही समझ में आता है, उदा। एसयूएम –

+0

खैर, ROW_NUMBER(), रैंक(), आदि, * (क्योंकि वे स्थिति/क्रम पर निर्भर विभिन्न मान वापस करते हैं) * लेकिन MIN(), MAX(), SUM() नहीं? – MatBailie

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