MySQL ORDER BY में पंक्ति स्थिति प्राप्त करता है


86

निम्नलिखित MySQL तालिका के साथ:

+-----------------------------+
+ id INT UNSIGNED             +
+ name VARCHAR(100)           +
+-----------------------------+

मैं तालिका में अन्य पंक्तियों के बीच एक एकल पंक्ति और उसकी स्थिति का चयन कैसे कर सकता हूं name ASC। यदि तालिका डेटा ऐसा दिखता है, तो नाम द्वारा क्रमबद्ध किया गया है:

+-----------------------------+
+ id | name                   +
+-----------------------------+
+  5 | Alpha                  +
+  7 | Beta                   +
+  3 | Delta                  +
+ .....                       +
+  1 | Zed                    +
+-----------------------------+

मैं उस Betaपंक्ति की वर्तमान स्थिति प्राप्त करने वाली पंक्ति का चयन कैसे कर सकता हूं ? मैं जो परिणाम सेट देख रहा हूँ वह कुछ इस तरह होगा:

+-----------------------------+
+ id | position | name        +
+-----------------------------+
+  7 |        2 | Beta        +
+-----------------------------+

मैं एक सरल SELECT * FROM tbl ORDER BY name ASCफिर PHP में पंक्तियों की गणना कर सकता हूं , लेकिन केवल एक पंक्ति के लिए संभावित बड़े परिणाम को लोड करना बेकार लगता है।



जवाबों:


120

इसे इस्तेमाल करो:

SELECT x.id, 
       x.position,
       x.name
  FROM (SELECT t.id,
               t.name,
               @rownum := @rownum + 1 AS position
          FROM TABLE t
          JOIN (SELECT @rownum := 0) r
      ORDER BY t.name) x
 WHERE x.name = 'Beta'

... एक अद्वितीय स्थिति मान प्राप्त करने के लिए। यह:

SELECT t.id,
       (SELECT COUNT(*)
          FROM TABLE x
         WHERE x.name <= t.name) AS position,
       t.name    
  FROM TABLE t      
 WHERE t.name = 'Beta'

... संबंधों को समान मूल्य देगा। IE: यदि दूसरे स्थान पर दो मान हैं, तो दोनों में 2 की स्थिति होगी जब पहली क्वेरी उनमें से एक को 2 का स्थान देगी, और 3 को दूसरे को ...


@ कार्य: कहने के लिए कुछ भी नहीं है - विश्लेषणात्मक कार्यों (PostgreSQL, Oracle, SQL सर्वर, DB2 ...) का समर्थन करने वाले प्रतियोगी की ओर बढ़ने के अलावा कोई विकल्प नहीं है
OMG Ponies

2
@OMGPonies बस एक अल्पविराम के बाद भूल जाते हैं position, लेकिन यह एकदम सही है।
पियरलैंड

मुझे पता है कि यह काफी पुरानी पोस्ट है, लेकिन मुझे इसी तरह के समाधान की आवश्यकता है। हालाँकि, जब आंतरिक जोड़, समूह और क्रम से "स्थिति" फ़ील्ड का उपयोग करते हैं, तो इन पर ध्यान नहीं दिया जाता है और मूल्य को मिलाया जाता है। कोई उपाय?
डैनियल

@ डैनियल आपको एक नया प्रश्न पूछना चाहिए और शायद इस एक को देखें।
पीरबहोर

@actual, चूंकि यह एक पंक्ति के लिए एक क्वेरी है, इसलिए यहां महत्वपूर्ण प्रदर्शन चिंता नहीं होनी चाहिए। यदि आप पूर्ण सूची के रैंक प्राप्त करने का प्रयास कर रहे हैं, तो यह अलग है, लेकिन आप केवल "धोखा" दे सकते हैं और अंकों के आधार पर एक अंतर्निहित रैंक का उपयोग कर सकते हैं।
अगमलाकर

20

यह एकमात्र तरीका है जिसके बारे में मैं सोच सकता हूं:

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'

2
+1 अच्छा ट्रिक ... हालाँकि आप शायद name <= 'Beta'इसके बजाय उपयोग करना चाहते हैं
डैनियल वैसलो

यह दृष्टिकोण positionसंबंधों के लिए समान मूल्य देगा ।
OMG पोंजी

(मेरी पिछली टिप्पणी हटा दी गई - मैं गलत था) ... यदि आप LIMIT 1वहाँ जोड़ते हैं तो क्या होगा? एक टाई के मामले में, आपको टाई की अंतिम स्थिति के साथ सिर्फ एक पंक्ति मिल जाएगी।
डैनियल वासल्लो

यदि ओपी गारंटी दे सकता है कि nameक्षेत्र अद्वितीय है - तो क्वेरी को अधिक जटिल बनाने का कोई कारण नहीं है। अगर वह नहीं कर सकता है - तो चलो बंधे नामों के लिए उसकी परिणाम अपेक्षाओं की प्रतीक्षा करें।
झटके

8

यदि क्वेरी सरल है और लौटे परिणाम सेट का आकार संभावित रूप से बड़ा है, तो आप इसे दो प्रश्नों में विभाजित करने का प्रयास कर सकते हैं।

संकीर्ण-डाउन फ़िल्टरिंग मानदंड वाली पहली क्वेरी केवल उस पंक्ति का डेटा पुनर्प्राप्त करने के लिए, और दूसरी क्वेरी स्थिति की गणना करने के लिए क्लॉज़ के COUNTसाथ उपयोग करती है WHERE

उदाहरण के लिए आपके मामले में

प्रश्न 1:

SELECT * FROM tbl WHERE name = 'Beta'

क्वेरी 2:

SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'

हम 2M रिकॉर्ड वाली तालिका में इस दृष्टिकोण का उपयोग करते हैं और यह OMG पॉनीज़ के दृष्टिकोण से अधिक मापनीय है।


4

अन्य उत्तर मेरे लिए बहुत जटिल लगते हैं।

यहां एक आसान उदाहरण मिलता है , मान लें कि आपके पास कॉलम वाली एक तालिका है:

userid | points

और आप उपयोगकर्ता को बिंदुओं के आधार पर क्रमबद्ध करना चाहते हैं और पंक्ति स्थिति (उपयोगकर्ता की "रैंकिंग") प्राप्त करते हैं, तो आप उपयोग करते हैं:

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, userid, points
FROM
    ourtable
ORDER BY points DESC

num आप पंक्ति पद (रैंकिंग) देता है।

यदि आपके पास MySQL 8.0+ है तो आप ROW_NUMBER () का उपयोग करना चाहते हैं


2

तालिका में एक पंक्ति की स्थिति यह दर्शाती है कि लक्षित पंक्ति की तुलना में कितनी पंक्तियाँ "बेहतर" हैं।

तो, आपको उन पंक्तियों को गिनना चाहिए।

COPORT (*) + 1 का चयन करें, tableजहां name<'Beta'

एक टाई के मामले में, उच्चतम स्थिति वापस आ जाती है।

यदि आप मौजूदा "बीटा" पंक्ति के बाद "बीटा" के समान नाम के साथ एक और पंक्ति जोड़ते हैं, तो वापस लौटी स्थिति 2 हो जाएगी, क्योंकि वे वर्गीकरण में एक ही स्थान साझा करेंगे।

आशा है कि यह उन लोगों की मदद करता है जो भविष्य में कुछ इसी तरह की खोज करेंगे, जैसा कि मेरा मानना ​​है कि प्रश्न के मालिक ने पहले ही अपने मुद्दे को हल कर लिया है।


2

मुझे एक बहुत ही समान मुद्दा मिला है, इसलिए मैं एक ही सवाल नहीं पूछूंगा, लेकिन मैं यहां साझा करूंगा कि मैंने क्या किया, मुझे एवीजी द्वारा एक समूह का उपयोग भी करना पड़ा, और आदेश भी। हस्ताक्षर और समाज के साथ छात्र हैं, और मुझे उन्हें रैंक करना था (दूसरे शब्दों में, मैं पहले एवीजी को शांत करता हूं, फिर उन्हें डीईएससी में आदेश देता हूं, और फिर अंत में मुझे स्थिति (मेरे लिए रैंक) जोड़ने की आवश्यकता थी, इसलिए मैंने किया) कुछ बहुत समान रूप सर्वश्रेष्ठ उत्तर यहाँ, एक छोटे से बदलाव है कि मेरी समस्या को समायोजित) के साथ:

मैंने positionबाहरी चयन में अंत में (मेरे लिए रैंक) कॉलम रखा

SET @rank=0;
SELECT @rank := @rank + 1 AS ranking, t.avg, t.name
  FROM(SELECT avg(students_signatures.score) as avg, students.name as name
FROM alumnos_materia
JOIN (SELECT @rownum := 0) r
left JOIN students ON students.id=students_signatures.id_student
GROUP BY students.name order by avg DESC) t 

यह उत्तर स्वीकृत की तुलना में समझने में आसान था। +1
एरिक सस्टैंडैंड

1

मैं स्वीकृत उत्तर से गुजर रहा था और यह थोड़ा जटिल लग रहा था इसलिए यहाँ इसका सरलीकृत संस्करण है।

SELECT t,COUNT(*) AS position FROM t      
 WHERE name <= 'search string' ORDER BY name

0

मुझे इसी प्रकार की समस्या है जहां मुझे टेबल की रैंक ( सूचकांक ) की आवश्यकता है order by votes desc। निम्नलिखित मेरे लिए ठीक काम करता है।

Select *, ROW_NUMBER() OVER(ORDER BY votes DESC) as "rank"
From "category_model"
where ("model_type" = ? and "category_id" = ?)

-9

ऐड सिंटैक्स के साथ आपकी आवश्यकता हो सकती है

LIMIT

इसलिए उपयोग करें

SELECT * FROM tbl ORDER BY name ASC LIMIT 1

अगर तुम सिर्फ एक पंक्ति की जरूरत है ..


यह उत्तर यहाँ समस्या का समाधान नहीं है। आप इसे हटाने पर विचार कर सकते हैं
Damián Rafael Lattenero
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.