保证Sqlite的“ IN”运算符的搜索顺序?

时间:2019-10-03 17:07:46

标签: sqlite deterministic in-operator

我正在执行类似Sqlite3的查询

SELECT * FROM nodes WHERE name IN ('name1', 'name2', 'name3', ...) LIMIT 1

我是否保证它将首先搜索name1,然后搜索name2,依此类推?这样,通过将输出限制为1,我知道我根据IN子句中的项目顺序找到了第一笔匹配吗?

更新:经过一些测试,无论IN的顺序如何,它似乎总是返回索引中的第一个匹配项。它使用名称索引的顺序。有什么方法可以强制执行搜索顺序?

1 个答案:

答案 0 :(得分:1)

不能保证返回的行的顺序与IN之后括号中各项的顺序匹配。
您可以做的是在语句中使用INSTR()函数来使用ORDER BY

SELECT * FROM nodes 
WHERE name IN ('name1', 'name2', 'name3') 
ORDER BY INSTR(',name1,name2,name3,', ',' || name || ',')
LIMIT 1

此代码使用IN子句中的相同列表作为字符串,其中各项以相同顺序排列,并用逗号连接和分隔,假设各项不包含逗号。
这样,结果将按照其在列表中的位置进行排序,然后LIMIT 1将返回结果中的第一个,它更接近列表的开始。

获得相同结果的另一种方法是使用CTE返回列表,同时返回Id作为结果的期望顺序,该结果将与表连接:

WITH list(id, item) AS (
  SELECT 1, 'name1' UNION ALL 
  SELECT 2, 'name2' UNION ALL 
  SELECT 3, 'name3' 
)
SELECT n.* 
FROM nodes n INNER JOIN list l
ON l.item = n.name 
ORDER BY l.id
LIMIT 1 

或者:

WITH list(id, item) AS (
  SELECT * FROM (VALUES 
    (1, 'name1'), (2, 'name2'), (3, 'name3')
  )
)
SELECT n.* 
FROM nodes n INNER JOIN list l
ON l.item = n.name 
ORDER BY l.id
LIMIT 1 

这样,您不必重复两次列表。