2011-04-18 60 views
4

试图做同样的事情this question,但这次在sqlite中。在我目前的应用程序中,我需要能够做这种类型的查询: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); 

回答

4

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来测试这个。

+0

我不知道是否mysql优化器足够聪明,知道这与元组语法相同。 – bukzor 2011-04-27 05:38:03

+0

@ bukzor:对。我会纠正我的答案。 – 2011-04-27 11:51:20

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 

字符串连接是非常昂贵和不够简洁,但它的工作方式相同,并看起来非常相似。

+0

只有在转义连接的字符串时,这才是通用的。你认为这比@ catcall的答案有更好的表现吗? – bukzor 2013-01-29 17:06:02