2012-11-10 24 views
18

मेरे पास id, year और count के साथ एक तालिका है।पोस्टग्रेएसक्यूएल MAX और ग्रुप

मैं हर id के लिए MAX(count) हो और year रखने जब ऐसा होता है करना चाहते हैं, तो मैं इस क्वेरी बनाने:

ERROR: column "table.year" must appear in the GROUP BY clause or be used in an aggregate function

तो:

SELECT id, year, MAX(count) 
FROM table 
GROUP BY id; 

दुर्भाग्य से, यह मुझे एक त्रुटि देता है मैं कोशिश करता हूं:

SELECT id, year, MAX(count) 
FROM table 
GROUP BY id, year; 

लेकिन फिर, यह डी MAX(count) नहीं करते हैं, यह सिर्फ तालिका को दिखाता है। मुझे लगता है क्योंकि year और id द्वारा समूहित करते समय, यह उस विशिष्ट वर्ष के id के लिए अधिकतम हो जाता है।

तो, मैं यह प्रश्न कैसे लिख सकता हूं? मैं id के MAX(count) और उस वर्ष होने पर वर्ष प्राप्त करना चाहता हूं।

+1

यदि {आईडी, वर्ष} अद्वितीय हैं, तो अधिकतम (चीज़) '' चीज़ 'जैसा ही है।यह भी ध्यान रखें कि "गिनती" एक कीवर्ड है, (और साल के साथ-साथ कुछ बोलीभाषाओं में, आईआईआरसी) – wildplasser

+0

आप प्रत्येक आईडी के साथ किस वर्ष प्राप्त करना चाहते हैं? "वर्ष" नहीं है, फिर एक और है, शायद आप 'MAX (वर्ष)' चाहते हैं? – mata

+0

हाँ, वे अद्वितीय हैं इसलिए मुझे चीज़ मिलती है। मैं ids MAX (चीज़) प्राप्त करना चाहता हूं और यह भी देखें कि कौन सा वर्ष होता है। (मैं अपने कोड में गिनती नहीं लिख रहा था, बस एक उदाहरण) –

उत्तर

21
select * 
from (
    select id, 
     year, 
     thing, 
     max(thing) over (partition by id) as max_thing 
    from the_table 
) t 
where thing = max_thing 

या:

select t1.id, 
     t1.year, 
     t1.thing 
from the_table t1 
where t1.thing = (select max(t2.thing) 
        from the_table t2 
        where t2.id = t1.id); 

या

select t1.id, 
     t1.year, 
     t1.thing 
from the_table t1 
    join ( 
    select id, max(t2.thing) as max_thing 
    from the_table t2 
    group by id 
) t on t.id = t1.id and t.max_thing = t1.thing 

या

with max_stuff as (
    select id, max(t2.thing) as max_thing 
    from the_table t2 
    group by id 
) 
select t1.id, 
     t1.year, 
     t1.thing 
from the_table t1 
    join max_stuff t2 
    on t1.id = t2.id 
    and t1.thing = t2.max_thing 
+0

@ user1504577 अधिकतम हो: इन सभी प्रश्नों में प्रति वर्ष एकाधिक मान वापस आते हैं जब एकाधिक वर्ष अधिकतम साझा करते हैं गिनती। आपको इस सामान्य मामले में जो चाहते हैं उसे परिभाषित करना होगा। सब दिखाओ? एक चुनें? नवीनतम/जल्द से जल्द/जो कुछ भी? एक कॉलम में वर्षों की एक सूची दिखाएं? –

+0

@a_horse_with_no_name क्या आप इनमें से प्रत्येक प्रश्न के पेशेवरों और विपक्ष की व्याख्या कर सकते हैं? – Stratus3D

36

कम से कम (और संभवतः सबसे तेजी से) क्वेरी (एक अलग अंकन के साथ पिछले के रूप में ही) DISTINCT ON के साथ होगा , एसक्यूएल मानक DISTINCT खंड के एक PostgreSQL विस्तार:

SELECT DISTINCT ON (1) 
     id, count, year 
FROM tbl 
ORDER BY 1, 2 DESC, 3; 

संख्या SELECT सूची में क्रमसूचक स्थान नहीं हैं, आप इसे बाहर भी वर्तनी लिख सकता:

SELECT DISTINCT ON (id) 
     id, count, year 
FROM tbl 
ORDER BY id, count DESC, year; 

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

यह एक अच्छी तरह से परिभाषित तरीके से संबंधों को तोड़ता है (जब कई वर्ष समान अधिकतम गणना साझा करते हैं): सबसे पुराना वर्ष चुनें। यदि आपको परवाह नहीं है, तो ORDER BY से year छोड़ें। या year DESC के साथ नवीनतम वर्ष चुनें।

अधिक विवरण, लिंक, एक बेंचमार्क इस करीबी उत्तर में एक संभवतः तेजी से समाधान:

एक तरफ: एक वास्तविक जीवन क्वेरी में, आप से कुछ का उपयोग नहीं होता कॉलम नाम id कॉलम नाम के लिए एक गैर-वर्णनात्मक विरोधी-पैटर्न है, countreserved word in standard SQL और count() पोस्टग्रेस में एक समग्र कार्य है।

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