按sql in()子句中值的顺序排序

zaqlnxep  于 2021-06-15  发布在  Mysql
关注(0)|答案(13)|浏览(334)

我想知道是否有其他方法(可能更好的方法)按in()子句中值的顺序排序。
问题是我有两个查询,一个获取所有id,另一个检索所有信息。第一个创建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()子句的顺序不同。
我发现的一个解决方案是将所有的id放入一个带有自动递增字段的temp表中,然后将该字段加入到第二个查询中。
有更好的选择吗?
注意:由于第一个查询是“由用户”运行的,而第二个查询是在后台进程中运行的,因此无法使用子查询将2合并为1个查询。
我使用的是mysql,但我想让它注意到其他dbs也有哪些选项可能会有用。

2ledvvac

2ledvvac1#

获取排序数据。

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

6qfn3psc2#

试一试:

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可能需要稍加调整才能使相关子查询正常工作,但基本原则应该是合理的。

gstyhher

gstyhher3#

对于oracle,john使用instr()函数的解决方案是可行的。这是一个稍微不同的解决方案- SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)

368yc8dk

368yc8dk4#

in子句描述一组值,而这些值的集合没有顺序。
您的解决方案与一个连接,然后在 display_order 列是最接近正确的解;其他任何东西都可能是dbms特有的黑客行为(或者正在用标准sql中的olap函数做一些事情)。当然,join是最接近可移植的解决方案(尽管使用 display_order 值可能有问题)。请注意,您可能需要选择排序列;这曾经是标准sql中的一个要求,尽管我相信它在不久前作为一个规则被放宽了(可能早在sql-92之前)。

fhg3lkii

fhg3lkii5#

使用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()` 以相同的顺序运行。
sxissh06

sxissh066#

如果要使用mssqlserver2008+中查询输入的值对查询进行任意排序,可以通过动态创建表并执行类似的连接(使用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语句替换为其他执行相同操作的语句(但在ansisql中),则这应该适用于任何sql数据库。
注意:当查询大于100左右的记录集时,所创建表中的第二列(ordertbl.orderidx)是必需的。我最初没有orderidx列,但发现当结果集大于100时,我必须显式地按该列排序;无论如何,在sql server express 2014中。

2uluyalo

2uluyalo7#

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)

真的很棒

qnyhuwrf

qnyhuwrf8#

请参见下面的如何获取排序数据。

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
uqdfh47h

uqdfh47h9#

使用mysql find\ in\ u set函数:

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

lp0sw83n10#

想到两种解决方案:
order by case id when 123 then 1 when 456 then 2 else null end asc order by instr(','||id||',',',123,456,') asc ( instr() 来自甲骨文;也许你有 locate() 或者 charindex() 或者类似的)

6tr1vspr

6tr1vspr11#

我的第一个想法是编写一个查询,但您说这是不可能的,因为一个由用户运行,另一个在后台运行。如何存储要从用户传递到后台进程的id列表?为什么不把它们放在一个临时表中,用一列表示顺序呢。
那么这个怎么样:
用户界面位运行并将值插入到您创建的新表中。它将插入id、位置和某种工作编号标识符)
作业编号传递给后台进程(而不是所有ID)
后台进程从步骤1中的表中进行选择,然后您加入以获取所需的其他信息。它使用where子句中的作业编号,并按position列排序。
后台进程完成后,将根据作业标识符从表中删除。

ecr0jaav

ecr0jaav12#

我刚刚试过在ms sql server中执行此操作,但没有字段():

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

请注意,我也允许复制。

7dl7o3gd

7dl7o3gd13#

我认为你应该设法存储你的数据的方式,你只需做一个连接,这将是完美的,所以没有黑客和复杂的事情正在进行。
例如,我有一个“最近播放”的曲目ID列表,在sqlite上我只做了:

SELECT * FROM recently NATURAL JOIN tracks;

相关问题