按照SQL IN()子句中的值的顺序sorting

我想知道如果有一个IN()子句中的值的顺序sorting(可能更好的方法)。

问题是,我有2个查询,一个获取所有的ID和第二个检索所有的信息。 第一个创build我希望第二个sorting的ID的顺序。 这些ID以正确的顺序放在IN()子句中。

所以它会是(非常简化)的东西:

SELECT id FROM table1 WHERE ... ORDER BY display_order, name SELECT name, description, ... WHERE id IN ([id's from first]) 

问题是第二个查询不会返回结果以相同的顺序将ID放入IN()子句中。

我find的一个解决scheme是将所有的ID放入一个临时表中,然后将自动递增字段join到第二个查询中。

有更好的select吗?

注意:由于第一个查询是由“用户”运行的,第二个查询是在后台进程中运行的,因此无法使用子查询将2合并为1查询。

我正在使用MySQL,但是我认为注意其他数据库有什么选项也许是有用的。

使用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

如果将ID以相同的顺序粘贴到IN()子句和FIELD()函数中,这将完全符合您的要求。

请参阅以下如何获取sorting数据。

 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 

想到两个解决scheme:

  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()或类似的东西)

IN子句描述一组值,并且集合没有顺序。

join你的解决scheme,然后在display_order列上sorting是最接近正确的解决scheme; 其他任何东西都可能是一个特定于DBMS的破解(或者在标准SQL中使用OLAP函数做一些事情)。 当然,连接是最接近便携式的解决scheme(尽pipe使用display_order值生成数据可能会有问题)。 请注意,您可能需要select订购栏; 过去是标准SQL中的一个要求,尽pipe我相信前一段时间(也许早在SQL-92)就已经放松了。

Ans获取sorting数据。

 SELECT ... FROM ... ORDER BY FIELD(user_id,5,3,2,...,50) LIMIT 10 

对于Oracle,John的解决scheme使用instr()函数。 这里有一些稍微不同的解决scheme – SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)

 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) 

工作真的很棒

使用MySQL FIND_IN_SET函数:

  SELECT * FROM table_name WHERE id IN (..,..,..,..) ORDER BY FIND_IN_SET (coloumn_name, .., .., ..); 

如果您想使用MS SQL Server 2008+中查询input的值对查询进行任意sorting,则可以通过dynamic创build表格并执行类似的连接(使用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语句replace为执行相同操作的其他语句,但是在ANSI SQL中,则这应该适用于任何SQL数据库。

注:查询大于100左右的logging集时,创build表(orderTbl.orderIdx)中的第二列是必需的。 我本来没有一个orderIdx列,但发现结果集大于100我不得不显式sorting该列; 在SQL Server Express 2014反正。

我的第一个想法是写一个单一的查询,但你说这是不可能的,因为一个是由用户运行,另一个是在后台运行。 你如何存储从用户传递到后台进程的ID列表? 为什么不把它们放在一个临时表格中,以表示订单。

那么这个怎么样:

  1. 用户界面位运行并将值插入到您创build的新表中。 它会插入ID,位置和某种工作号码标识符)
  2. 工作号码被传递给后台进程(而不是所有的ID)
  3. 后台进程从第1步中的表中进行select,并join以获取所需的其他信息。 它使用WHERE子句中的作业编号和位置列的顺序。
  4. 后台进程完成后,根据作业标识从表中删除。

我认为你应该设法存储你的数据,你只需要简单地join,这将是完美的,所以没有黑客和复杂的事情发生。

我有例如一个“最近播放”的轨道ID列表,在SQLite上我只是做:

 SELECT * FROM recently NATURAL JOIN tracks; 

给这个镜头:

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

WHEEs可能会稍微调整一下,以使相关子查询正常工作,但基本原则应该是正确的。

我只是试图做到这一点是MS SQL Server,我们没有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 

请注意,我也允许重复。