sqlite元组比较

buk*_*zor 6 sql sqlite row-value-expression

试着和这个问题做同样的事情,但这次是在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
Run Code Online (Sandbox Code Playgroud)

并得到('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 |
+-------+---------+-------+
Run Code Online (Sandbox Code Playgroud)

在sqlite中实现这一目标的最有效方法是什么?请记住,这是一个玩具示例,我的实际应用程序具有包含更多列和数据类型以及数亿行的表.

如果解决方案可以轻松扩展到更多/更少的列,那就更好了.


元组比较:

元组按字典顺序排序,这意味着序列的排序与它们的第一个不同元素的顺序相同.例如,(1,2,x)<(1,2,y)返回与x <y相同的值.

值得注意的是SQL-92(以及mysql,oracle,postresql)正确实现了这一点.该标准使用"行值构造函数"来表示我称之为元组的内容.该行为在第8.2.7节,第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);
Run Code Online (Sandbox Code Playgroud)

Mik*_*ll' 6

SQLite不支持元组比较.但是行构造函数是一种简写.您可以使用更复杂的WHERE子句获得相同的结果.我省略了该LIMIT 1子句,以便更容易看到两个查询都返回相同的集合.(在支持行构造函数的平台上,即.)

这种比较

ROW(a,b) <= ROW(c,d) 
Run Code Online (Sandbox Code Playgroud)

相当于

a < c OR (a = c AND b <= d)
Run Code Online (Sandbox Code Playgroud)

您可以根据需要将其扩展到尽可能多的列.

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
Run Code Online (Sandbox Code Playgroud)

我没有用数据中的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
Run Code Online (Sandbox Code Playgroud)

我不知道这是多久以前介绍的.

  • [行值](https://www.sqlite.org/rowvalue.html) 于 2016 年 10 月 14 日为 3.15.0 版本添加了支持,随后进行了多项修复,最后一项修复于 2018 年 4 月 2 日 (3.23.0)。 0)。有关详细信息,请参阅 https://www.sqlite.org/changes.html。 (2认同)