SQL: сравнение кортежей

В моем текущем приложении я должен быть может выполнить этот тип запроса:

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, если это помогает. Вы также можете предположить, что эти столбцы имеют ПЕРВИЧНЫЙ или УНИКАЛЬНЫЙ индекс.

Если решение легко расширяется до большего / меньшего количества столбцов, это даже лучше.


Сравнение кортежей:

Некоторые спрашивали, поэтому я должен указать это в вопросе. Кортежи упорядочены лексикографически, это означает, что последовательности упорядочены так же, как их первые отличающиеся элементы. Например, (1,2, x) <(1,2, y) возвращает то же, что и 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);

Добавление этого индекса, кажется, приводит к лексикографической сортировке таблицы, что интересно. Это не так в нашей производственной системе.

14
задан Lukas Eder 12 April 2013 в 14:03
поделиться