মান তালিকা অনুসারে অর্ডার করুন


165

পোস্টগ্র্রেএসকিউএল 8.3 এ আমার একটি সাধারণ এসকিউএল ক্যোয়ারী রয়েছে যা বেশ কিছু মন্তব্য ধরেছে। আমি ধারাটিতেIN নির্মাণের জন্য মানগুলির বাছাই করা তালিকা সরবরাহ করি WHERE:

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

এটি একটি সালিশী ক্রমে মন্তব্যগুলি দেয় যা আমার মতো আইডির মতো হয় 1,2,3,4

আমি তালিকা মত সাজানো ফলে সারি চান INকনস্ট্রাক্ট: (1,3,2,4)
কীভাবে অর্জন করব?


এবং আমি কেবল বাছাইয়ের জন্য একটি নতুন টেবিল তৈরি না করাকে পছন্দ করব (এসকিউএল বিশুদ্ধতা সত্ত্বেও)।
নিউটক্র্যাকার

2
আমি এখন একগুচ্ছ উত্তর পেয়েছি। আমি কি কিছু ভোটদান এবং মন্তব্য পেতে পারি যাতে আমি জানি যে বিজয়ী! সমস্ত ধন্যবাদ :-)
নিউট্র্যাকার

উত্তর:


106

আপনি এটি পোস্টগ্রিএসকিউএল 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
@ ব্যবহারকারী 80168 আইএন ক্লজে হাজার মান থাকলে? কারণ হাজার হাজার রেকর্ডের জন্য আমি এটি করতে পেরেছি
কমল

@ কমল তার জন্য আমি ব্যবহার করেছি with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
নুমেনন

66

এটি খুঁজে পাওয়া খুব কঠিন এবং এটি ছড়িয়ে দিতে হয়েছে কেবল কারণ: মাইএসকিউএল এ এটি আরও সহজভাবে করা যেতে পারে , তবে আমি জানি না এটি অন্যান্য এসকিউএল এ কাজ করে কিনা।

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

পোস্টগ্রিস 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এবং এটি দুর্দান্ত কাজ করছে বলে মনে হচ্ছে :-)
কাজম্যাগনাস

পোস্টগ্রিসে কাজ করে এবং মনে হয় এটি সেরা সমাধান!
মাইক সিজেন্ডেল

এই সমাধানটি আমার পক্ষে কৌশলটি করেছে, কিন্তু: কেউ কী গবেষণা করেছে যে এই সমাধানটি কার্যক্ষমতার ভিত্তিতে কীভাবে করছে? এটি ধারাগুলি দ্বারা একাধিক ক্রম যুক্ত করে। সুতরাং এটি (আমি এখনও এটি পরীক্ষা করিনি) ক্রমবর্ধমান অর্ডার-আইডির সাথে ধীরে ধীরে ধীরে ধীরে পেতে পারি? এ সম্পর্কিত যে কোনও তথ্য অত্যন্ত প্রশংসিত হবে!
ফ্যাবিয়ান শোনার

1
ত্রুটি: টার্গেটের তালিকাগুলিতে সর্বাধিক 1664 টি এন্ট্রি থাকতে পারে -> আপনি যখন দীর্ঘ জিজ্ঞাসা চালানোর চেষ্টা করেন ...
ফাতখান ফৌজী

@ মানঙ্গো এমএস এসকিউএল কোন সংস্করণ মনে করতে পারছি না। 2012 হতে পারে।
বিকো

42

সঙ্গে 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দফা, যা এই সর্বোত্তম উত্তর এই প্রোগ্রামটিতে তোলে ... এখন শুধুমাত্র মাইএসকিউএল জন্য অনুরূপ কিছু খুঁজে না ...
Stijn De Witt

1
আমার প্রিয় উত্তর তবে নোট করুন যে অ্যারে_পজিশনটি বিগিন্টের সাথে কাজ করে না এবং আপনাকে কাস্ট করতে হবে: order by array_position(array[42,48,43], c.id::int);যা কিছু ক্ষেত্রে বাগের দিকে নিয়ে যেতে পারে।
আন্ড্রে

1
@aandre নীচের কাস্টিংটি ভালভাবে কাজ করছে (পোস্টগ্র্রেসে কমপক্ষে 12 টিতে) array_position(array[42, 48, 43]::bigint[], c.id::bigint), সুতরাং এটি কাটাতে হবে bigintনা int
ভিক

29

পোস্টগ্রিসে এটি করার আর একটি উপায় হ'ল idxফাংশনটি ব্যবহার করা ।

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

idxএখানে বর্ণিত হিসাবে প্রথমে ফাংশনটি তৈরি করতে ভুলবেন না : http://wiki.postgresql.org/wiki/Array_Index


11
: এই ফাংশনটি একটি এক্সটেনশন যে পোস্টগ্রি দিয়ে আসে মধ্যে এখন পাওয়া যায় postgresql.org/docs/9.2/static/intarray.html সঙ্গে এটি ইনস্টল করুন CREATE EXTENSION intarray;
অ্যালেক্স কাহন

1
কেবল আরও সংক্ষেপে, অ্যামাজন আরডিএস ব্যবহারকারীদের জন্য, আরওআর মাইগ্রেশন ফাংশন enable_extensionআপনাকে এতক্ষণ সক্রিয় করতে দেবে যতক্ষণ না আপনার অ্যাপ্লিকেশন ব্যবহারকারী rds_superuserগ্রুপটির সদস্য ।
ডেভ এস

PG 9.6.2 তে PG :: অপরিজ্ঞাতকৃত ফাংশন: ত্রুটি: ফাংশন আইডিএক্স (পূর্ণসংখ্যা [], পূর্ণসংখ্যার) উপস্থিত নেই
ইয়াকব উবাইদী

আপনাকে ধন্যবাদ, সেরা উত্তর যখন অ্যালেক্সা কাহন এর মন্তব্যের সাথে মিলিত
অ্যান্ড্রু

21

পোস্টগ্র্যাস্কল-এ:

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, না?
অ্যালানজডস

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
অবশ্যই, আমি তাদের সম্পর্কে মন্তব্য করতে পারেন। এসকিউএলগুলিতে ভাল কিছু রয়েছে এবং জিনিসগুলি এটি ভাল হয় না। এসকিউএল এ ক্ষেত্রে ভাল নয়। আপনি যে ভাষা থেকে প্রশ্নগুলি তৈরি করছেন তা কেবল ফলাফলকে সাজান; এটি আপনাকে কাঁদতে এবং দাঁতে দাঁত ঘষতে সাহায্য করবে। এসকিউএল একটি সেট-ভিত্তিক ভাষা এবং সেটগুলি সংগ্রহের আদেশ দেওয়া হয় না।
kquinn

হুঁ ... এটি কি ব্যক্তিগত অভিজ্ঞতা এবং পরীক্ষার ভিত্তিতে? আমার পরীক্ষিত অভিজ্ঞতা হ'ল এটি অর্ডার দেওয়ার জন্য বেশ কার্যকর কৌশল। (তবে, গ্রহণযোগ্য উত্তর সামগ্রিকভাবে ভাল কারণ এটি "আইএন (...)" ধারাটি সরিয়ে দেয়)। মনে রাখবেন যে কোনও যুক্তিসঙ্গত ফলাফল সেট আকারের জন্য, সেটটি অর্জন করা ব্যয়বহুল অংশ হওয়া উচিত। একবার এটি কয়েকশ রেকর্ড বা তারও কম নেমে গেলে, বাছাই করা তুচ্ছ।
dkretz

INধারাটিতে কয়েক হাজার মান থাকলে কী হবে ? কারণ আমি হাজার হাজার রেকর্ডের জন্য এটি করতে পেরেছি।
কমল

2

এটি করার জন্য, আমি মনে করি আপনার কাছে সম্ভবত একটি অতিরিক্ত "অর্ডার" টেবিল থাকা উচিত যা আইডির ম্যাপিংকে অর্ডার করার জন্য সংজ্ঞা দেয় (কার্যকরভাবে আপনার নিজের প্রশ্নের প্রতিক্রিয়া যা বলেছিল তা করে), যা আপনি নিজের নির্বাচনের অতিরিক্ত কলাম হিসাবে ব্যবহার করতে পারেন আপনি তারপর বাছাই করতে পারেন।

এইভাবে, আপনি স্পষ্টভাবে ডেটাবেসটিতে আপনার যে ক্রমটি চান তা ক্রমবর্ধমানভাবে বর্ণনা করুন যেখানে এটি হওয়া উচিত।


এটি এটি করার সঠিক উপায় বলে মনে হচ্ছে। তবে আমি ফ্লাইতে সেই অর্ডারিং টেবিলটি তৈরি করতে চাই। আমি উত্তরের একটিতে একটি ধ্রুবক টেবিল ব্যবহার করার পরামর্শ দিয়েছি। আমি যখন শত বা হাজার হাজার মন্তব্যে ডিল করছি তখন কি এটি পারফরম্যান্স হতে চলেছে?
নটক্র্যাকার

2

সাকস সিকোয়েন্স, কেবল 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
আপনার উত্তর প্রায় দেপেসের মতো একই, কেবল সি.আইডি ইন সরান (1,3,2,4)। যাইহোক তার ভাল, তিনি যোগদান করুন, যতটা সম্ভব এএনএসআই এসকিউএল যোগদানের উপায় ব্যবহার করুন, টেবিল কমা টেবিল ব্যবহার করবেন না। আমার উত্তরটি মনোযোগ সহকারে পড়া উচিত ছিল, দুটি কলামটি কীভাবে উপন্যাস করতে হবে তা নির্ধারণ করতে আমার খুব কষ্ট হচ্ছে, প্রথমে আমি এটি চেষ্টা করেছি: (মানগুলি (1,1) x (আইডি, সাজানো_আর্ডার) হিসাবে, (3,2), (2,3), (4,4)) y হিসাবে। তবে কোনও লাভ হয়নি :-D আপনার উত্তরটি আমাকে একটি ক্লু সরবরাহ করতে পারত যদি আমি তা মনোযোগ সহকারে পড়ি :-)
মাইকেল বুয়েন

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;

[Edit]

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

ধন্যবাদ মাইকেল তবে অজানা ফাংশনটি আমার পিএসকিউএল-এর জন্য বিদ্যমান বলে মনে হচ্ছে না এবং আমি এটি ডক্সেও খুঁজে পাই না। এটি কি কেবল 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)

এখানে, [বিবিএস] হল প্রধান টেবিল যার আইডিস নামে একটি ক্ষেত্র রয়েছে, এবং, আইডিএস মন্তব্যসমূহের সংরক্ষণ করে এমন অ্যারে।

Postgresql 9.6 এ পাস করেছে


আপনি এই কোয়েরি পরীক্ষা করেছেন?
ললিথকুমার

এখানে, মনে রাখবেন, আইডিএস হ'ল একটি অ্যারে টাইপ, যেমন {1,2,3,4}}
ব্যবহারকারী 6161156

0

ইতিমধ্যে যা বলা হয়েছিল সে সম্পর্কে ভিজ্যুয়াল ছাপ পেতে দিন get উদাহরণস্বরূপ আপনার কয়েকটি টাস্ক সহ একটি টেবিল রয়েছে:

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

ক্রেডিট @ ব্যবহারকারী 80168


-1

আমি অন্য সমস্ত পোস্টারের সাথে একমত যেগুলি "এটি করবেন না" বা "এসকিউএল এটিতে ভাল নয়" বলে। আপনি যদি কিছু মতামত অনুসারে বাছাই করতে চান তবে আপনার সারণির মানদণ্ডটি ধরে রাখতে এবং সেই মান অনুসারে বাছাই করতে আপনার টেবিলগুলির মধ্যে একটিতে আরও একটি পূর্ণসংখ্যা কলাম যুক্ত করুন। উদাহরণস্বরূপ "মন্তব্য দ্বারা অর্ডার করুন। DESC বাছাই করুন" আপনি যদি প্রতি বার এটি আলাদা ক্রমে বাছাই করতে চান তবে ... এসকিউএল এই ক্ষেত্রে আপনার জন্য হবে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.