2009-01-20 17 views
19

के n वें सदस्य का चयन करते हैं मैंएसक्यूएल समूह

class | age 
-------------- 
1  20  
3  56 
2  11 
1  12 
2  20 

की तरह एक उपयोगकर्ता तालिका है तो मैं आसानी से अधिकतम के साथ मिनट की जगह के माध्यम से

select class, min(age) 
from user 
group by class; 

इसी तरह, प्रत्येक वर्ग में सबसे कम उम्र के उपयोगकर्ता प्राप्त कर सकते हैं, मैं सबसे पुराना हो सकता हूं। लेकिन मैं प्रत्येक कक्षा में 10 वीं सबसे छोटी (या सबसे पुराना) कैसे प्राप्त कर सकता हूं? वैसे, मैं MySQL v.5.0 का उपयोग कर रहा हूँ।

चीयर्स,

उत्तर

0

यह एसक्यूएल सर्वर में बहुत आसान है:

select 
    * 
from(
    select 
     *, 
     row_number() over(order by age asc) as eldest 
    from class order by age asc) a 
where a.eldest = 10 

कि पैटर्न के बाद, MySQL के लिए, मुझे लगता है कि आप इस को देखने के लिए चाहते हैं: http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/

+0

देता कड़ी में विधि काम करता है लेकिन इसके बारे में एक सा है एक हैक यह भी बहुत तेज़ है। उत्पादन के लिए, एक ऑफ ठीक है! –

11
SELECT a.class, 
(
    SELECT b.age 
    FROM users b 
    WHERE b.class = a.class 
    ORDER BY age 
    LIMIT 1,1 
) as age 
FROM users a 
GROUP BY a.class 

प्रत्येक वर्ग में दूसरा सबसे छोटा होगा। यदि आप 10 वें सबसे कम उम्र के चाहते थे, तो आप LIMIT 9,1 करेंगे और यदि आप 10 वें सबसे पुराने चाहते थे, तो आप ORDER BY age DESC करेंगे।

+1

इससे मुझे 10 वीं सबसे पुराना समग्र मिलेगा, प्रत्येक कक्षा में 10 वां सबसे पुराना नहीं। –

+0

हूप्स, ध्यान नहीं दिया कि वह इसे समूहीकृत करना चाहता था। फिक्सिंग ... –

+0

यह MySQL v5.5: ERROR 1235 (42000): MySQL का यह संस्करण अभी तक 'LIMIT और IN/ALL/ANY/SOME subquery' – Marcus

0
SELECT 
    userid, 
    class, 
    age, 
    ( SELECT COUNT(1) FROM user 
      WHERE class = c.class AND age > u.age 
    ) AS oldercount 
FROM user AS u 
WHERE oldercount = 9 
GROUP BY class 

या

SELECT userid, 
     class, 
     age 
    FROM user AS u  
    WHERE (SELECT COUNT(1) FROM class WHERE class = c.class AND age > u.age) = 9 
GROUP BY class 
+0

का समर्थन नहीं करता है यदि दो लोगों की उम्र समान थी और आप केवल उनमें से एक को वापस करना चाहते थे तो एक अनूठी कुंजी की आवश्यकता है। –

+0

पहली क्वेरी त्रुटि का कारण बनती है: "अज्ञात कॉलम 'छोटा' जिसमें 'खंड' ' –

+0

दोनों स्रोत तालिका में प्रत्येक रिकॉर्ड के लिए पूरी कक्षा को पुन: स्कैन करते हैं। एक वर्ग कानून मारने के बिना करने योग्य होना चाहिए ... – MatBailie

1

केवल एसक्यूएल स्वतंत्र तरीके (भले ही आप सबक्वेरी mysql < 5 की जरूरत नहीं है)

select u1.class, u1.age, count(*) from  user u1 join user u2 
on u1.class = u2.class and u1.age >= u2.age 
group by u1.class, u1.age 
having count(*) = [number] 

आप हो जाता है [संख्या] वर्ग

प्रति सबसे पुराना
select u1.class, u1.age, count(*) from  user u1 join user u2 
on u1.class = u2.class and u1.age <= u2.age 
group by u1.class, u1.age 
having count(*) = [number] 

आपको प्रति वर्ग [संख्या] सबसे कम उम्र

यदि दो लोगों की उम्र समान है तो यह काम नहीं कर सकता क्योंकि दोनों लौटाए जाते हैं। यदि आप केवल उनमें से एक को वापस करना चाहते हैं तो आपको एक अनूठी कुंजी की आवश्यकता होगी और क्वेरी अधिक जटिल होगी।

0

कोई जवाब यह है कि उस पर एक तालिका संयोजन स्वयं एक वर्ग कानून बनाएगा ...

- a JOIN b ON a.class = b.class AND a.age >= b.age 
- on average the >= condition will be true for half the class 

- 6 people in a class 
->6*6/2 = 18 

- 10 people in a class 
->10*10/2 = 50 

-> very rapid growth 

तालिका आकार के रूप में बढ़ने प्रदर्शन तेजी से नीचा होगा। यदि आप चीजों को छोटा रखते हैं और वे ज्यादा नहीं बढ़ेंगे, तो क्या यह एक मुद्दा है? आपका वहाँ कॉल ...

एक वैकल्पिक अधिक कोड शामिल है, लेकिन रैखिक बढ़ता है ...

  • पहले, नई तालिका intoa सभी रिकॉर्ड, एक पहचान क्षेत्र के साथ, कक्षा तो उम्र
  • द्वारा आदेश दिया सम्मिलित
  • अब, प्रत्येक वर्ग के लिए, मिन (आईडी) को खोजने के
  • अब, प्रत्येक वर्ग के लिए, रिकॉर्ड जहां है = मिन (आईडी) + 8 (9 ज्येष्ठ के लिए)

एक बहुत हैं rinf पिछले 2 चरणों को करने के तरीकों के बारे में। मैं व्यक्तिगत रूप से उपयोग करता हूं ...

SELECT 
    [USER_WITH_IDS].id, 
    [USER_WITH_IDS].class, 
    [USER_WITH_IDS].age 
FROM 
    [USER_WITH_IDS] 
WHERE 
    [USER_WITH_IDS].id = (
          SELECT 
           MIN([min].ID) + 8 
          FROM 
           [USER_WITH_IDS] AS [min] 
          WHERE 
           [min].class = [USER_WITH_IDS].class 
         ) 

यह क्या देता है ...

  • एक पास को नई ID बनाने के लिए
  • एक पास प्रत्येक वर्ग के लिए मिन (आईडी) प्राप्त करने के लिए
  • एक पास रिकॉर्ड आप

  • जरूरत है पाने के लिए और कैसे अच्छा पर निर्भर करता है ऑप्टिमाइज़र एक इंडेक्स (कक्षा तब आईडी) का उपयोग करके, अंतिम 2 पास को 1 पास में जोड़ने की अनुमति देगा।

2 या 3 पास, कोई फर्क नहीं पड़ता कि तालिका या कक्षा का आकार कितना बड़ा हो जाता है। रेखीय, नहीं वर्ग के कानून ...

7

यहाँ NNth रिकॉर्ड oldest

SELECT * 
FROM users k 
WHERE N = (SELECT 
      COUNT(DISTINCT age) 
      FROM users u 
      WHERE k.age >= u.age 
       AND k.class = u.class 
      GROUP BY u.class) 

प्रस्तुत करता है और यह Nth रिकॉर्ड youngest

SELECT * 
FROM users k 
WHERE N = (SELECT 
      COUNT(DISTINCT age) 
      FROM users u 
      WHERE k.age <= u.age 
       AND k.class = u.class 
      GROUP BY u.class) 
+0

आप मेरा दिन बचाओ, धन्यवाद !!!!!! – mzalazar

+0

कमाल !! इसे उत्तर के रूप में चिह्नित किया जाना चाहिए –

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