मूल्य सूची द्वारा आदेश


166

मेरे पास PostgreSQL 8.3 में एक सरल एसक्यूएल क्वेरी है जो टिप्पणियों का एक समूह बनाती है। मैं खंड में निर्माण के लिए मूल्यों की एक क्रमबद्ध सूची प्रदान करता हूं :INWHERE

SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));

यह एक अनियंत्रित क्रम में टिप्पणी करता है जो मेरे आईडी की तरह होता है 1,2,3,4

मैं INनिर्माण में सूची की तरह हल पंक्तियों चाहते हैं (1,3,2,4):।
कैसे प्राप्त करें?


और मैं सिर्फ एक छांटना (SQL शुद्धता के बावजूद) के लिए एक नई तालिका नहीं बनाना पसंद करूंगा।
नटक्रैकर

2
मुझे अब उत्तरों का एक गुच्छा मिला है। क्या मुझे कुछ मतदान और टिप्पणियां मिल सकती हैं, इसलिए मुझे पता है कि विजेता कौन है! धन्यवाद सभी :-)
नटक्रैकर

जवाबों:


107

आप इसे बहुत आसानी से (PostgreSQL 8.2 में प्रस्तुत) मान्य (), () के साथ कर सकते हैं।

सिंटेक्स इस तरह होगा:

select c.*
from comments c
join (
  values
    (1,1),
    (3,2),
    (2,3),
    (4,4)
) as x (id, ordering) on c.id = x.id
order by x.ordering

2
@ user80168 यदि IN खंड में हजारों मान हैं तो क्या होगा? क्योंकि मुझे इसे हज़ारों रिकॉर्ड करने के लिए मिल गया है
कमाल

@kamal उसके लिए मैंने प्रयोग किया है with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
नौमेनन

66

सिर्फ इसलिए कि इसे ढूंढना बहुत मुश्किल है और इसे फैलाना है: mySQL में यह बहुत सरल हो सकता है , लेकिन मुझे नहीं पता कि यह अन्य SQL में काम करता है या नहीं।

SELECT * FROM `comments`
WHERE `comments`.`id` IN ('12','5','3','17')
ORDER BY FIELD(`comments`.`id`,'12','5','3','17')

3
मूल्यों की सूची दो बार , दो अलग-अलग तरीकों से प्रदान की जानी है। इतना आसान नहीं। स्वीकृत उत्तर को केवल एक बार इसकी आवश्यकता होती है (भले ही अधिक वर्बोज़ फैशन में)। और यह आधुनिक पोस्टग्रैज के साथ और भी सरल है (जैसा कि नए उत्तरों में दिखाया गया है)। साथ ही, यह सवाल पोस्टग्रैज के बारे में भी लगता है।
एरविन ब्रान्डेसटेटर

8
ERROR: cannot pass more than 100 arguments to a function
बोरालियोबो

54

Postgres 9.4 या बाद में, यह संभवतः सबसे सरल और सबसे तेज़ है :

SELECT c.*
FROM   comments c
JOIN   unnest('{1,3,2,4}'::int[]) WITH ORDINALITY t(id, ord) USING (id)
ORDER  BY t.ord;

विस्तृत विवरण:


46

मुझे लगता है कि यह तरीका बेहतर है:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
    ORDER BY  id=1 DESC, id=3 DESC, id=2 DESC, id=4 DESC

1
मैं बाध्य मूल्यों के साथ ऐसा करने में सक्षम था, अर्थात: ... order by id=? desc, id=? desc, id=? descऔर यह ठीक काम करने के लिए लगता है :-)
KajMagnus

पोस्टग्रेज में काम करता है और सबसे अच्छा समाधान लगता है!
माइक संजील

इस समाधान ने मेरे लिए चाल चली, लेकिन: क्या किसी ने शोध किया कि यह समाधान प्रदर्शन-वार कैसे कर रहा है? यह खंडों द्वारा बहु क्रम जोड़ता है। इसलिए यह हो सकता है (मैं इसे अभी तक परीक्षण नहीं किया है) आदेश आईडी की बढ़ती संख्या के साथ तेजी से धीमी हो? इस पर कोई जानकारी बहुत सराहना की जाएगी!
फेबियन शॉनर

1
त्रुटि: लक्ष्य सूची में अधिकतम 1664 प्रविष्टियाँ हो सकती हैं -> जब आप लंबी क्वेरी चलाने की कोशिश करें ...
फतखन फौजी

@ मैनंगो एमएस एसक्यूएल। कौन सा संस्करण याद नहीं कर सकते। हो सकता है 2012.
biko

43

Postgres 9.4 के साथ यह थोड़ा कम किया जा सकता है:

select c.*
from comments c
join (
  select *
  from unnest(array[43,47,42]) with ordinality
) as x (id, ordering) on c.id = x.id
order by x.ordering;

या व्युत्पन्न तालिका के बिना थोड़ा अधिक कॉम्पैक्ट:

select c.*
from comments c
  join unnest(array[43,47,42]) with ordinality as x (id, ordering) 
    on c.id = x.id
order by x.ordering

मैन्युअल रूप से असाइन करने / प्रत्येक मान के लिए स्थिति बनाए रखने की आवश्यकता को हटाना।

Postgres 9.6 के साथ यह प्रयोग किया जा सकता है array_position():

with x (id_list) as (
  values (array[42,48,43])
)
select c.*
from comments c, x
where id = any (x.id_list)
order by array_position(x.id_list, c.id);

सीटीई का उपयोग किया जाता है ताकि मूल्यों की सूची को केवल एक बार निर्दिष्ट करने की आवश्यकता हो। यदि यह महत्वपूर्ण नहीं है, तो यह भी लिखा जा सकता है:

select c.*
from comments c
where id in (42,48,43)
order by array_position(array[42,48,43], c.id);

यह पूरी INसूची को WHEREक्लॉज से फिर से क्लॉज में नहीं दोहराता है ORDER BY, जो इसे सबसे अच्छा उत्तर imho बनाता है ... अब केवल MySQL के लिए कुछ समान खोजने के लिए ...
Stijn de Witt

1
मेरा पसंदीदा उत्तर लेकिन ध्यान दें कि array_position बिगिन के साथ काम नहीं करता है और आपको कास्ट करने की आवश्यकता होगी: order by array_position(array[42,48,43], c.id::int);जो, कुछ मामलों में बग हो सकता है।
1935 में एँद्रे सिप

1
@aaandre निम्नलिखित कास्टिंग ठीक काम कर रही है (पोस्टग्रेज 12 में कम से कम) array_position(array[42, 48, 43]::bigint[], c.id::bigint), इसलिए इसे कम bigintकरने की आवश्यकता नहीं है int
विक

29

Postgres में इसे करने का दूसरा तरीका idxफ़ंक्शन का उपयोग करना होगा ।

SELECT *
FROM comments
ORDER BY idx(array[1,3,2,4], comments.id)

idxफ़ंक्शन को बनाना न भूलें , जैसा कि यहाँ वर्णित है: http://wiki.postgresql.org/wiki/Array-Index


11
यह फ़ंक्शन अब एक एक्सटेंशन में उपलब्ध है जो PostgreSQL के साथ आता है: postgresql.org/docs/9.2/static/intarray.html इसे स्थापित करें CREATE EXTENSION intarray;
एलेक्स कहन

1
अमेज़ॅन आरडीएस उपयोगकर्ताओं के लिए बस आगे बढ़ते हुए, आरओआर माइग्रेशन फ़ंक्शन enable_extensionआपको इसे तब तक सक्रिय करने देगा जब तक आपका ऐप उपयोगकर्ता rds_superuserसमूह का सदस्य न हो ।
डेव एस।

पीजी में 9.6.2 पीजी :: अनिर्धारित: कार्य: त्रुटि: फ़ंक्शन आईडीएक्स (पूर्णांक [], पूर्णांक) मौजूद नहीं है
याकूब उबैदी

धन्यवाद, सबसे अच्छा जवाब जब @ AlexKahn की टिप्पणी के साथ संयुक्त
एंड्रयू

21

Postgresql में:

select *
from comments
where id in (1,3,2,4)
order by position(id::text in '1,3,2,4')

2
हम ... यह कीड़े position(id::text in '123,345,3,678')। आईडी आईडी 3से पहले मेल खाएगा 345, न?
alanjds

4
मुझे लगता है कि आप सही हैं और दोनों को एक शुरुआत और अंत परिसीमन करने की आवश्यकता होगी, हो सकता है जैसे: स्थिति द्वारा आदेश (',' आईडी = पाठ: ',' in ', 1,3,2,4, || ')
माइकल रश

3

कुछ और शोध करने पर मुझे यह समाधान मिला:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4)) 
ORDER BY CASE "comments"."id"
WHEN 1 THEN 1
WHEN 3 THEN 2
WHEN 2 THEN 3
WHEN 4 THEN 4
END

हालांकि यह क्रियात्मक लगता है और बड़े डेटासेट के साथ प्रदर्शन समस्याएँ हो सकती हैं। क्या कोई इन मुद्दों पर टिप्पणी कर सकता है?


7
ज़रूर, मैं उन पर टिप्पणी कर सकता हूं। ऐसी चीजें हैं जो एसक्यूएल में अच्छी हैं, और यह उन चीजों में अच्छी नहीं है। SQL इस पर अच्छा नहीं है। जिस भी भाषा में आप प्रश्न बना रहे हैं, उसमें परिणाम को क्रमबद्ध करें; यह आपको दांतों के बहुत अधिक घूमने और गलने से बचाएगा। एसक्यूएल एक सेट-ओरिएंटेड भाषा है, और सेट को संग्रह का आदेश नहीं दिया जाता है।
kquinn

हम्म् ... क्या यह व्यक्तिगत अनुभव और परीक्षण पर आधारित है? मेरा परीक्षण अनुभव यह है कि यह ऑर्डर करने के लिए काफी प्रभावी तकनीक है। (हालांकि, स्वीकृत उत्तर कुल मिलाकर बेहतर है क्योंकि यह "IN (...)" खंड को समाप्त करता है। याद रखें कि किसी भी उचित परिणाम सेट आकार के लिए, सेट को प्राप्त करना महंगा हिस्सा होना चाहिए। एक बार जब यह कई सौ रिकॉर्ड या उससे कम हो जाता है, तो छंटनी तुच्छ होती है।
dkretz 15

यदि INखंड में हजारों मान हैं तो क्या होगा ? क्योंकि मुझे इसे हजारों रिकॉर्ड के लिए करना है।
कमाल

2

ऐसा करने के लिए, मुझे लगता है कि आपके पास संभवतः एक अतिरिक्त "ORDER" तालिका होनी चाहिए, जो ऑर्डर करने के लिए आईडी की मैपिंग को परिभाषित करती है (प्रभावी रूप से अपने खुद के प्रश्न के बारे में आपकी प्रतिक्रिया क्या कर रही है), जिसे आप तब अपने चयन पर एक अतिरिक्त कॉलम के रूप में उपयोग कर सकते हैं जो फिर आप इसे सॉर्ट कर सकते हैं।

इस तरह, आप स्पष्ट रूप से डेटाबेस में अपनी इच्छा के अनुसार ऑर्डर करने का वर्णन करते हैं, जहां यह होना चाहिए।


यह ऐसा करने का सही तरीका लगता है। हालाँकि मैं मक्खी पर उस ऑर्डरिंग टेबल को बनाना चाहूंगा। मैंने उत्तर में एक निरंतर तालिका का उपयोग करने का सुझाव दिया है। जब मैं सैकड़ों या हजारों टिप्पणियों के साथ काम कर रहा हूं तो क्या यह प्रदर्शन करने वाला है?
नटक्रैकर

2

Sans SEQUENCE, केवल 8.4 पर काम करता है:

select * from comments c
join 
(
    select id, row_number() over() as id_sorter  
    from (select unnest(ARRAY[1,3,2,4]) as id) as y
) x on x.id = c.id
order by x.id_sorter

1
SELECT * FROM "comments" JOIN (
  SELECT 1 as "id",1 as "order" UNION ALL 
  SELECT 3,2 UNION ALL SELECT 2,3 UNION ALL SELECT 4,4
) j ON "comments"."id" = j."id" ORDER BY j.ORDER

या यदि आप अच्छाई पर बुराई पसंद करते हैं:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
ORDER BY POSITION(','+"comments"."id"+',' IN ',1,3,2,4,')

0

और यहाँ एक और समाधान है जो काम करता है और एक निरंतर तालिका ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ) का उपयोग करता है :

SELECT * FROM comments AS c,
(VALUES (1,1),(3,2),(2,3),(4,4) ) AS t (ord_id,ord)
WHERE (c.id IN (1,3,2,4)) AND (c.id = t.ord_id)
ORDER BY ord

लेकिन फिर से मुझे यकीन नहीं है कि यह प्रदर्शन है।

मुझे अब उत्तरों का एक गुच्छा मिला है। क्या मुझे कुछ मतदान और टिप्पणियां मिल सकती हैं, इसलिए मुझे पता है कि विजेता कौन है!

सबको शुक्रीया :-)


1
आपका उत्तर लगभग डेसज़ के समान है, बस c.ID IN (1,3,2,4) निकालें। वैसे भी उनकी स्थिति बेहतर है, वह जॉइन का उपयोग करते हैं, जितना संभव हो उतना एएनएसआई एसक्यूएल के जुड़ने के तरीके का उपयोग करें, टेबल कॉमा टेबल का उपयोग न करें। मुझे आपके उत्तर को ध्यान से पढ़ना चाहिए, मुझे यह जानने में कठिन समय मिल रहा है कि दो कॉलमों को कैसे उतारा जाए, पहले मैंने यह कोशिश की: (मान (1,1) x (id, Sort_order), (3,2) के रूप में, (2,3), (4,4)) y के रूप में। लेकिन कोई फायदा नहीं हुआ: -यदि आपका जवाब मुझे एक सुराग दे सकता है अगर मैंने इसे ध्यान से पढ़ा है :-)
माइकल ब्यूएन

0
create sequence serial start 1;

select * from comments c
join (select unnest(ARRAY[1,3,2,4]) as id, nextval('serial') as id_sorter) x
on x.id = c.id
order by x.id_sorter;

drop sequence serial;

[संपादित करें]

अनावश्यक अभी तक 8.3 में निर्मित नहीं है, लेकिन आप स्वयं (किसी भी * की सुंदरता) बना सकते हैं:

create function unnest(anyarray) returns setof anyelement
language sql as
$$
    select $1[i] from generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;

वह फ़ंक्शन किसी भी प्रकार में काम कर सकता है:

select unnest(array['John','Paul','George','Ringo']) as beatle
select unnest(array[1,3,2,4]) as id

धन्यवाद माइकल, लेकिन अनावश्यक फ़ंक्शन मेरे PSQL के लिए मौजूद नहीं है और मैं डॉक्स में इसका कोई उल्लेख नहीं पा रहा हूँ। क्या यह केवल 8.4 है?
नटक्रैकर

अनावश्यक अभी 8.3 में अंतर्निहित नहीं है, लेकिन आप स्वयं को लागू कर सकते हैं। ऊपर दिए गए कोड को देखें
माइकल ब्यूएन

0

मेरे विचार से अनुक्रम का उपयोग करने वाले संस्करण पर थोड़ा सुधार:

CREATE OR REPLACE FUNCTION in_sort(anyarray, out id anyelement, out ordinal int)
LANGUAGE SQL AS
$$
    SELECT $1[i], i FROM generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;

SELECT 
    * 
FROM 
    comments c
    INNER JOIN (SELECT * FROM in_sort(ARRAY[1,3,2,4])) AS in_sort
        USING (id)
ORDER BY in_sort.ordinal;

0
select * from comments where comments.id in 
(select unnest(ids) from bbs where id=19795) 
order by array_position((select ids from bbs where id=19795),comments.id)

यहाँ, [bbs] मुख्य सारणी है जिसमें एक फ़ील्ड है जिसे ids कहा जाता है, और, id वह सरणी है जो टिप्पणियों को संग्रहीत करती है।

postgresql में पारित 9.6


क्या आपने इस प्रश्न का परीक्षण किया?
lalithkumar

यहाँ, याद रखें, आईडी एक सरणी प्रकार है, जैसे, {1,2,3,4}।
user6161156

0

पहले से ही कहा गया था के बारे में एक दृश्य छाप देता है। उदाहरण के लिए आपके पास कुछ कार्यों के साथ एक तालिका है:

SELECT a.id,a.status,a.description FROM minicloud_tasks as a ORDER BY random();

 id |   status   |   description    
----+------------+------------------
  4 | processing | work on postgres
  6 | deleted    | need some rest
  3 | pending    | garden party
  5 | completed  | work on html

और आप कार्यों की सूची इसकी स्थिति के अनुसार क्रमबद्ध करना चाहते हैं। स्थिति स्ट्रिंग मानों की एक सूची है:

(processing, pending,  completed, deleted)

चाल को प्रत्येक स्थिति मान देने के लिए एक अंतराल है और सूची को क्रमबद्ध करना है:

SELECT a.id,a.status,a.description FROM minicloud_tasks AS a
  JOIN (
    VALUES ('processing', 1), ('pending', 2), ('completed', 3), ('deleted', 4)
  ) AS b (status, id) ON (a.status = b.status)
  ORDER BY b.id ASC;

जिससे होता है:

 id |   status   |   description    
----+------------+------------------
  4 | processing | work on postgres
  3 | pending    | garden party
  5 | completed  | work on html
  6 | deleted    | need some rest

क्रेडिट @ user80168


-1

मैं अन्य सभी पोस्टरों से सहमत हूं जो कहते हैं कि "ऐसा मत करो" या "SQL उस पर अच्छा नहीं है"। यदि आप टिप्पणियों के कुछ पहलुओं को क्रमबद्ध करना चाहते हैं तो अपने मानदंड को रखने के लिए अपनी किसी तालिका में एक और पूर्णांक कॉलम जोड़ें और उस मान के आधार पर छाँटें। उदाहरण के लिए "ORDER BY comments.sort DESC" यदि आप इन्हें हर बार एक अलग क्रम में क्रमबद्ध करना चाहते हैं ... तो इस मामले में SQL आपके लिए नहीं होगा।

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