在我当前的应用程序中,我需要能够执行这种类型的查询:
SELECT MIN((colA, colB, colC)) FROM mytable WHERE (colA, colB, colC) BETWEEN (200, 'B', 'C') AND (1000, 'E', 'F')
并(333, 'B', 'B')给出以下数据的答案:
(333, 'B', 'B')
+------+------+------+ | colA | colB | colC | +------+------+------+ | 99 | A | A | | 200 | A | Z | | 200 | B | B | | 333 | B | B | | 333 | C | D | | 333 | C | E | | 333 | D | C | | 1000 | E | G | | 1000 | F | A | +------+------+------+
在实际的SQL中最有效的方法是什么?请记住,这是一个示例,我的实际应用程序中的表具有不同的列和数据类型以及数亿行。我使用MySQL,如果有帮助的话。您还可以假定这些列上具有PRIMARY或UNIQUE索引。
如果该解决方案很容易扩展到更多/更少的列,那就更好了。
元组比较:
有几个人问过,所以我应该把这个问题。元组按字典顺序排序,这意味着序列与其第一个不同元素的排序相同。例如,(1,2,x)<(1,2,y)返回与x <y相同的值。
值得注意的是,SQL(或至少是mysql)正确地实现了这一点:
mysql> select (200, 'B', 'C') < (333, 'B', 'B') and (333, 'B', 'B') < (1000, 'E', 'F'); +--------------------------------------------------------------------------+ | (200, 'B', 'C') < (333, 'B', 'B') and (333, 'B', 'B') < (1000, 'E', 'F') | +--------------------------------------------------------------------------+ | 1 | +--------------------------------------------------------------------------+ 1 row in set (0.00 sec)
这是创建示例所需的SQL:
create table mytable select 333 colA, 'B' colB, 'B' colC; insert into mytable values (200, 'B', 'B'), (333, 'C', 'D'), (1000, 'E', 'G'), (200, 'A', 'Z'), (1000, 'F', 'A'), (333, 'C', 'E'), (333, 'D', 'C'), (99, 'A', 'A'); alter table mytable add unique index myindex (colA, colB, colC);
添加此索引似乎会使表按字典顺序排序,这很有趣。在我们的生产系统中并非如此。
做就是了:
SELECT colA , colB , colC FROM mytable WHERE ( ('A', 'B', 'C') <= (colA, colB, colC ) ) AND ( (colA, colB, colC) <= ('D', 'E', 'F' ) ) ORDER BY colA, colB, colC LIMIT 1 ;
它工作正常。我怀疑它也应该很快。
这是等效的,但它可能具有更好的性能,具体取决于您的表:
SELECT m.colA , m.colB , m.colC FROM mytable m WHERE ( ('A', 'B', 'C') <= (m.colA, m.colB, m.colC) ) AND ( (m.colA, m.colB, m.colC) <= ('D', 'E', 'F') ) AND NOT EXISTS ( SELECT 1 FROM mytable b WHERE (b.colA, b.colB, b.colC) < (m. colA, m.colB, m.colC) AND ( ('A', 'B', 'C') <= (b.colA, b.colB, b.colC) ) );