尝试做与 this question 相同的事情, 但这次是在 sqlite 中。在我当前的应用程序中,我需要能够执行这种类型的查询:
SELECT First, Last, Score
FROM mytable
WHERE
('John', 'Jordan', 5) <= (First, Last, Score )
AND (First, Last, Score) <= ('Mike', 'Taylor', 50)
ORDER BY First, Last, Score
LIMIT 1
并得到 ('Liz', 'Jordan', 2)
的答案,给出以下数据:
+-------+---------+-------+
| First | Last | Score |
+-------+---------+-------+
| Liz | Jordan | 2 |
| John | Jordan | 2 |
| Liz | Lemon | 10 |
| Mike | Taylor | 100 |
| John | Jackson | 1000 |
| Mike | Wayne | 1 |
| Liz | Lemon | 20 |
| Liz | Meyers | 5 |
| Bruce | Jackson | 1 |
+-------+---------+-------+
在 sqlite 中实现这个最有效的方法是什么?请记住,这是一个玩具示例,我的实际应用程序有包含更多列和数据类型以及数亿行的表。
如果解决方案可以轻松扩展到更多/更少的列,那就更好了。
元组比较:
元组按字典顺序排序,这意味着序列的排序与其第一个不同的元素相同。例如,(1,2,x) < (1,2,y) 返回与 x < y 相同的结果。
值得注意的是,SQL-92(以及 mysql、oracle、postresql)正确地实现了这一点。该标准使用“行值构造函数”来表示我所说的元组。在 part 8.2.7, page 209 中定义了极其详细的行为.
下面是创建示例所需的 SQL:
create table mytable ( First char(20), Last char(20), Score int );
insert into mytable values ('Liz', 'Jordan', 2);
insert into mytable values ('John', 'Jordan', 2);
insert into mytable values ('Liz', 'Lemon', 10);
insert into mytable values ('Mike', 'Taylor', 100);
insert into mytable values ('John', 'Jackson', 1000);
insert into mytable values ('Mike', 'Wayne', 1);
insert into mytable values ('Liz', 'Lemon', 20);
insert into mytable values ('Liz', 'Meyers', 5);
insert into mytable values ('Bruce', 'Jackson', 1);
create unique index 'UNIQ' on mytable (First, Last, Score);
最佳答案
SQLite 不支持元组比较。但是行构造函数是一种简写。使用更复杂的 WHERE 子句可以获得相同的结果。我省略了 LIMIT 1
子句,以便更容易看出两个查询返回相同的集合。 (也就是说,在支持行构造函数的平台上。)
这个对比
ROW(a,b) <= ROW(c,d)
相当于
a < c OR (a = c AND b <= d)
您可以根据需要将其扩展到任意数量的列。
SELECT First, Last, Score
FROM mytable
WHERE
(('John' < First) OR
('John' = First AND 'Jordan' < Last) OR
('John' = First AND 'Jordan' = Last AND 5 <= Score))
AND ((First < 'Mike') OR
(First = 'Mike' AND Last < 'Taylor') OR
(First = 'Mike' AND Last = 'Taylor' AND Score <= 50))
ORDER BY First, Last, Score
Liz Jordan 2
Liz Lemon 10
Liz Lemon 20
Liz Meyers 5
我没有用数据中的 NULL 测试它。
截至 2018 年,SQLite 确实支持元组比较。 OP 的查询使用提供的 SQL 语句生成预期的输出。这种编写查询的方式也有效。 (我发现 between ... and ...
更具可读性。)
SELECT First, Last, Score
FROM mytable
WHERE (First, Last, Score ) between ('John', 'Jordan', 5) and ('Mike', 'Taylor', 50)
ORDER BY First, Last, Score
Limit 1
我不知道这是多久前推出的。
关于sqlite元组比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5698801/