【发布时间】:2011-07-27 06:38:46
【问题描述】:
在我当前的应用程序中,我需要能够执行这种类型的查询:
SELECT MIN((colA, colB, colC))
FROM mytable
WHERE (colA, colB, colC) BETWEEN (200, 'B', 'C') AND (1000, 'E', 'F')
得到(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)
值得注意的是,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);
添加这个索引似乎会导致表格按字典顺序排序,这很有趣。在我们的生产系统中并非如此。
【问题讨论】:
-
如何定义元组排序?
-
为了记录,
('B', 'K', 'K')的行不会满足BETWEEN条件,对吧? -
@ypercube:是的。 (B,K,K) 在 (A,B,C) 和 (D,E,F) 之间排序
-
@John Douthat:按字典顺序排列,这意味着序列的顺序与它们的第一个不同元素相同。例如,
(1,2,x) < (1,2,y)返回的结果与x < y相同。
标签: mysql sql aggregate-functions row-value-expression