尝试与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)&lt; (1,2,y)返回与x&lt;相同的值。年。
值得注意的是SQL-92(和mysql,oracle,postresql)正确实现了这一点。该标准使用&#34;行值构造函数&#34;表示我称之为元组的东西。行为在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);
答案 0 :(得分:6)
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
我不知道这是多久以前介绍的。
答案 1 :(得分:1)
我一直在通过使用字符串连接(||
)和字符序列来避免缺少元组比较,以确保字段不会“合并”并导致不正确的匹配(-
)。
(First, Last, Score) <= ('Mike', 'Taylor', 50)
变为
First||' - '||Last||' - '||Score <= 'Mike'||' - '||'Taylor'||' - '||'50'
或
First||' - '||Last||' - '||Score <= 'Mike - Taylor - 50'
所以你的SELECT
将是
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
字符串连接相当昂贵且简洁,但它的工作方式相同,看起来非常相似。