首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >sqlite元组比较

sqlite元组比较
EN

Stack Overflow用户
提问于 2011-04-18 13:20:09
回答 2查看 4.2K关注 0票数 6

尝试做与this question相同的事情,但这次是在sqlite中。在我当前的应用程序中,我需要能够执行这种类型的查询:

代码语言:javascript
复制
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)的答案:

代码语言:javascript
复制
+-------+---------+-------+
| 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:

代码语言:javascript
复制
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);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-27 06:42:46

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

此比较

代码语言:javascript
复制
ROW(a,b) <= ROW(c,d) 

等同于

代码语言:javascript
复制
a < c OR (a = c AND b <= d)

您可以根据需要将其扩展到任意多个列。

代码语言:javascript
复制
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

我没有在数据中使用NULLs进行测试。

从2018年开始,SQLite支持元组比较。OP的查询使用提供的SQL语句生成预期的输出。这种编写查询的方式也有效。(我发现between ... and ...的可读性更好。)

代码语言:javascript
复制
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

我不知道这是多久前引入的。

票数 6
EN

Stack Overflow用户

发布于 2013-01-30 00:33:09

我一直在使用字符串连接(||)和字符序列来确保字段不会“合并”并导致不正确的匹配(-),从而避免了缺乏元组比较的问题。

代码语言:javascript
复制
(First, Last, Score) <= ('Mike',  'Taylor',  50)

变成了

代码语言:javascript
复制
First||' - '||Last||' - '||Score <= 'Mike'||' - '||'Taylor'||' - '||'50'

代码语言:javascript
复制
First||' - '||Last||' - '||Score <= 'Mike - Taylor - 50'

所以你的SELECT应该是

代码语言:javascript
复制
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

字符串连接的代价很高,也不那么简洁,但它的工作方式相同,看起来也非常相似。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5698801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档