sqlite元组比较

标签 sql sqlite row-value-expression

尝试做与 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/

相关文章:

sql - 在 SQL "IN"子句中使用元组

sql - Apache Impala的迭代函数

java - 为什么 h2 数据库驱动程序 (JPA) 不创建表,而 postgres 却创建表

sql - 无法删除 SQL Server 2005 中的约束, "Could not drop constraint. See previous errors"

sql - Rails find_by_sql 依赖于数据库类型

python - Django 无法打开表中的数据库

SQLite 元组相等性比较

java - 装箱实体字段后强制 JPA 删除 NOT NULL 标志

node.js - 为nodejs安装sqlite3

java - 如何使用 jooq 编写具有多个字段的条件