SQL IN () क्लॉज़ में मानों के क्रम द्वारा ऑर्डर करना


154

मैं सोच रहा था कि क्या एक () खंड में मूल्यों के क्रम से दूर (संभवतः एक बेहतर तरीका) हो सकता है।

समस्या यह है कि मेरे पास 2 प्रश्न हैं, एक जो सभी आईडी प्राप्त करता है और दूसरा जो सभी जानकारी को पुनः प्राप्त करता है। पहला आईडी का क्रम बनाता है जो मैं चाहता हूं कि दूसरा ऑर्डर करे। आईडी को सही क्रम में एक () खंड में रखा गया है।

तो यह कुछ ऐसा होगा (अत्यंत सरलीकृत):

SELECT id FROM table1 WHERE ... ORDER BY display_order, name

SELECT name, description, ... WHERE id IN ([id's from first])

मुद्दा यह है कि दूसरी क्वेरी उसी क्रम में परिणाम नहीं लौटाती है जिसमें आईडी को IN () क्लॉज में डाला जाता है।

एक समाधान मैंने पाया है कि सभी आईडी को एक टेम्प्रेचर टेबल में एक ऑटो इंक्रीमेंटिंग फ़ील्ड के साथ रखा जाता है, जिसे बाद में दूसरी क्वेरी में शामिल किया जाता है।

क्या कोई बेहतर विकल्प है?

नोट: जैसा कि पहली क्वेरी "उपयोगकर्ता द्वारा" चलाई गई है और दूसरा एक पृष्ठभूमि प्रक्रिया में चलाया गया है, उप प्रश्नों का उपयोग करके 2 को 1 क्वेरी में संयोजित करने का कोई तरीका नहीं है।

मैं MySQL का उपयोग कर रहा हूं, लेकिन मैं सोच रहा हूं कि यह उपयोगी हो सकता है कि यह नोट किया जाए कि अन्य डीबी के लिए भी क्या विकल्प हैं।

जवाबों:


186

MySQL के FIELD()फ़ंक्शन का उपयोग करें :

SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])

FIELD() पहले पैरामीटर के सूचकांक को लौटाएगा जो पहले पैरामीटर (पहले पैरामीटर के अलावा अन्य) के बराबर है।

FIELD('a', 'a', 'b', 'c')

1 लौटेगा

FIELD('a', 'c', 'b', 'a')

3 लौटेंगे

यह वही होगा जो आप चाहते हैं यदि आप एक ही क्रम में आईडी IN()और FIELD()फ़ंक्शन में आईडी पेस्ट करते हैं ।


3
@Vojto एक मनमाना आदेश द्वारा छँटाई परिभाषा से धीमी है। यह अपनी पूरी कोशिश करता है क्योंकि कोई गारंटी नहीं है कि INऔर FIELDपैरामीटर समान हैं। प्रोग्राम कोड में ऐसा करना उस अतिरिक्त ज्ञान का उपयोग करके तेज हो सकता है। यदि आपके पास सर्वर का प्रदर्शन है, तो निश्चित रूप से, यह सर्वर के बजाय क्लाइंट पर यह बोझ डालना समझदारी भरा हो सकता है।
ivan_pozdeev 21

1
किस बारे में sqlite?
fnc12

15

डेटा को सॉर्ट करने का तरीका देखें।

SELECT ...
  FROM ...
 WHERE zip IN (91709,92886,92807,...,91356)
   AND user.status=1
ORDER 
    BY provider.package_id DESC 
     , FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10

11

दो समाधान जो वसंत को ध्यान में रखते हैं:

  1. order by case id when 123 then 1 when 456 then 2 else null end asc

  2. order by instr(','||id||',',',123,456,') asc

( instr()Oracle से है, हो सकता है आपके पास locate()या charindex()या ऐसा ही कुछ)


MySQL के लिए, FIELD_IN_SET () का भी उपयोग किया जा सकता है: dev.mysql.com/doc/refman/5.0/en/…
डैरिल हेन


6

यदि आप MS SQL Server 2008+ में क्वेरी द्वारा इनपुट किए गए मानों का उपयोग करके किसी क्वेरी पर मनमाने ढंग से सॉर्टिंग करना चाहते हैं , तो यह फ्लाई पर एक टेबल बनाकर और इस तरह से ज्वाइन (OP से नामकरण का उपयोग करके) किया जा सकता है।

SELECT table1.name, table1.description ... 
FROM (VALUES (id1,1), (id2,2), (id3,3) ...) AS orderTbl(orderKey, orderIdx) 
LEFT JOIN table1 ON orderTbl.orderKey=table1.id
ORDER BY orderTbl.orderIdx

यदि आप VALUES कथन को किसी और चीज़ से प्रतिस्थापित करते हैं जो समान कार्य करता है, लेकिन ANSI SQL में, तो यह किसी भी SQL डेटाबेस पर काम करना चाहिए।

नोट: बनाए गए तालिका में दूसरा कॉलम (ऑर्डरटब्ल.ऑर्डरआईएडीएक्स) आवश्यक है जब क्विकिंग रिकॉर्ड 100 या उससे अधिक सेट करता है। मेरे पास मूल रूप से एक ऑर्डरआईडीएक्स कॉलम नहीं था, लेकिन यह पाया गया कि परिणाम 100 से बड़े सेट के साथ मुझे उस कॉलम द्वारा स्पष्ट रूप से सॉर्ट करना था; SQL सर्वर एक्सप्रेस 2014 में वैसे भी।


यह प्रश्न MySQL के बारे में है ... यकीन नहीं है कि आपकी क्वेरी MySQL में काम करेगी।
डेरीएल हेन

2
@ डारिल, यह नहीं होगा। लेकिन यह पोस्ट शीर्ष परिणाम के रूप में आती है जब आप Google को IN के द्वारा ऑर्डर करने का तरीका बताते हैं, इसलिए मुझे लगा कि मैं इसे यहां पोस्ट कर सकता हूं और सामान्य कार्यप्रणाली सभी ANSI अनुरूप SQL सर्वरों पर लागू होती है (बस VALUES स्टेटमेंट को एक मानक के साथ बदलें) तालिका बनाने का तरीका)।
इयान

ध्यान दें, यह मेरे लिए काम किया, लेकिन बाद ही मैं के लिए संदर्भ की जगह orderTbl.orderKey, orderTbl.orderIndexद्वारा orderKey,orderIndex
पीटर

5
SELECT ORDER_NO, DELIVERY_ADDRESS 
from IFSAPP.PURCHASE_ORDER_TAB 
where ORDER_NO in ('52000077','52000079','52000167','52000297','52000204','52000409','52000126') 
ORDER BY instr('52000077,52000079,52000167,52000297,52000204,52000409,52000126',ORDER_NO)

वास्तव में बहुत अच्छा काम किया


ओरेकल पर मेरे लिए काम किया। जल्द और आसान। धन्यवाद।
मेनाचेम

4

IN क्लॉज मानों के एक सेट का वर्णन करता है, और सेट के पास ऑर्डर नहीं है।

सम्मिलित होने और फिर display_orderस्तंभ पर ऑर्डर देने के साथ आपका समाधान सबसे सही समाधान है; कुछ और शायद एक डीबीएमएस-विशिष्ट हैक (या मानक एसक्यूएल में ओएलएपी कार्यों के साथ कुछ सामान कर रहा है)। निश्चित रूप से, जुड़ाव सबसे लगभग पोर्टेबल समाधान है (हालांकि display_orderमूल्यों के साथ डेटा उत्पन्न करना समस्याग्रस्त हो सकता है)। ध्यान दें कि आपको आदेश देने वाले कॉलम का चयन करने की आवश्यकता हो सकती है; यह मानक SQL में एक आवश्यकता हुआ करता था, हालांकि मेरा मानना ​​है कि यह एक नियम के रूप में थोड़ी देर पहले (शायद SQL-92 के रूप में लंबे समय पहले) के रूप में आराम किया गया था।


2

Oracle के लिए, instr () फ़ंक्शन कार्यों का उपयोग करके जॉन का समाधान। यहाँ थोड़ा अलग समाधान है कि काम किया है - SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)



2

मैंने अभी यह करने की कोशिश की है कि MS SQL सर्वर जहाँ हमारे पास FIELD () नहीं है:

SELECT table1.id
... 
INNER JOIN
    (VALUES (10,1),(3,2),(4,3),(5,4),(7,5),(8,6),(9,7),(2,8),(6,9),(5,10)
    ) AS X(id,sortorder)
        ON X.id = table1.id
    ORDER BY X.sortorder

ध्यान दें कि मैं भी दोहराव की अनुमति दे रहा हूं।


1

मेरा पहला विचार एक ही क्वेरी लिखना था, लेकिन आपने कहा कि यह संभव नहीं था क्योंकि एक उपयोगकर्ता द्वारा चलाया जाता है और दूसरा पृष्ठभूमि में चलाया जाता है। आप उपयोगकर्ता की पृष्ठभूमि प्रक्रिया से गुजरने के लिए आईडी की सूची कैसे संग्रहीत कर रहे हैं? आदेश को सूचित करने के लिए उन्हें एक स्तंभ के साथ एक अस्थायी तालिका में क्यों नहीं रखा गया।

तो इस बारे में कैसे:

  1. उपयोगकर्ता इंटरफ़ेस बिट आपके द्वारा बनाई गई एक नई तालिका में मूल्यों को चलाता है और सम्मिलित करता है। यह आईडी, स्थिति और नौकरी संख्या पहचानकर्ता के कुछ प्रकार सम्मिलित करेगा)
  2. जॉब नंबर को बैकग्राउंड प्रोसेस (सभी आईडी के बजाय) में पास किया जाता है
  3. पृष्ठभूमि प्रक्रिया चरण 1 में तालिका से एक चयन करती है और आप अन्य जानकारी प्राप्त करने के लिए शामिल होते हैं जिनकी आपको आवश्यकता होती है। यह WHERE क्लॉज और पोजीशन कॉलम द्वारा ऑर्डर में जॉब नंबर का उपयोग करता है।
  4. जब काम खत्म हो जाता है तो पृष्ठभूमि की प्रक्रिया, नौकरी पहचानकर्ता के आधार पर तालिका से हटा देती है।

1

मुझे लगता है कि आपको अपने डेटा को इस तरह से स्टोर करने का प्रबंधन करना चाहिए कि आप बस एक जॉइन करेंगे और यह एकदम सही होगा, इसलिए कोई हैक और जटिल चीजें नहीं चलेंगी।

उदाहरण के लिए, मेरे पास "आइडेंटिफाईड" ट्रैक आईडी की सूची है, जो SQLite पर मैं बस करता हूं:

SELECT * FROM recently NATURAL JOIN tracks;

1
ओह, काश, जीवन इतना सरल होता
डार्लिन हेन

0

इसे एक शॉट दें:

SELECT name, description, ...
WHERE id IN
    (SELECT id FROM table1 WHERE...)
ORDER BY
    (SELECT display_order FROM table1 WHERE...),
    (SELECT name FROM table1 WHERE...)

WHEREs संभवत: सहसंबंधित उप-श्रेणियों को ठीक से काम करने के लिए थोड़ा ट्विकिंग लेगा, लेकिन मूल सिद्धांत ध्वनि होना चाहिए।


नोट देखें और यह भी, जैसा कि कहा गया है, क्वेरी उदाहरण बेहद सरल हैं, इसलिए मैं उन्हें उप क्वेरी के साथ 1 क्वेरी में संयोजित नहीं कर सकता।
डैरिल हेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.