sqlite元组比较

时间:2011-04-18 05:20:09

标签: 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)&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);

2 个答案:

答案 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

字符串连接相当昂贵且简洁,但它的工作方式相同,看起来非常相似。