2013-04-07 2 views
1

В алгоритме пользователи проходит запрос, например:Использование ROWNUM в подзапросов

SELECT o_orderdate, o_orderpriority FROM h_orders WHERE rownum <= 5 

Запрос возвращает следующее:

1996-01-02 5-LOW 
1996-12-01 1-URGENT 
1993-10-14 5-LOW 
1995-10-11 5-LOW 
1994-07-30 5-LOW 

Алгоритм нуждается счетчик для выбранных атрибутов (o_orderdate, o_orderpriority в приведенном выше примере), и поэтому он переписывает запрос по адресу:

SELECT o_orderdate, count(o_orderdate) FROM 
    (SELECT o_orderdate, o_orderpriority FROM h_orders WHERE rownum <= 5) 
GROUP BY o_orderdate 

Этот q uery возвращает следующее:

1992-01-01 5 

Однако предполагаемый результат:

1996-12-01 1 
1995-10-11 1 
1994-07-30 1 
1996-01-02 1 
1993-10-14 1 

Любая идея, как я могу переписать этап синтаксического анализа или как пользователь может передать синтаксически другой запрос на получение вышеуказанных результатов?

+0

На самом деле, ваш запрос возвращает свой желаемый результат из предоставленных данных - см http://sqlfiddle.com/#!4/93986/1. Некоторая ошибка, конечно? –

+0

На столе был указатель, который вызвал это поведение. Поскольку индекс находился в обоих столбцах, парсер базы данных выбирал кортежи в порядке индекса. Теперь, после того как я сбросил индекс, пример работает так, как вы показали. – DrRobotto

ответ

2

Строки, возвращаемые внутренним запросом, по существу не детерминированы, поскольку они зависят от порядка, в котором оптимизатор идентифицирует строки как часть требуемого набора данных. Изменение плана выполнения из-за измененных предикатов может изменить порядок возврата строк, а новые строки, добавленные в таблицу, также могут изменить, какие строки включены.

+0

Это верно, но запрос должен просто выбрать n строк, и не важно, какие из них. – DrRobotto

+1

В этом случае, как говорит Марк в вопросительном комментарии, ваш вопрос несовместим - это не результат, полученный от этого запроса и этих данных. Единственное объяснение заключается в том, что данные, спроецированные из внутреннего запроса, изменились, поэтому я подозреваю, что план выполнения изменился. –

0

Если вы всегда хотите, чтобы n строк, либо используйте distinct(o_orderdate) во внутреннем поиске, что сделает ненужным GROUP BY.

Или вы можете добавить еще внешнее select с rownum, чтобы получить n сгруппированных строк, например:

select o_orderdate, counter from 
(
    SELECT o_orderdate, count(o_orderdate) as counter FROM 
     (SELECT o_orderdate, o_orderpriority FROM h_orders) 

    GROUP BY o_orderdate 
) 
WHERE rownum <= 5 

Хотя результаты, скорее всего, будет бесполезным, так как они будут undeterministic (как упомянуто Дэвид Олдридж).

+0

Проблема этого запроса заключается в том, что он сканирует все отношение h_orders. В настоящее время соотношение содержит около 10^15 кортежей. Таблица используется только для эталонных тестов, поэтому необходимы разные срезы в начале выполнения. Детерминизм ничем не изменяет результаты тестов алгоритма. – DrRobotto

+0

как насчет использования ключевого слова 'distinct'? вы всегда будете получать записи 'n', но все они будут иметь 1 в качестве счета. Поведение вашего исходного запроса прекрасно, хотя если вам не нужны именно «n» результаты. – gordonk

0

Как ваш внешний запрос не делает использования «o_orderpriority», почему бы не просто избавиться от подзапроса и просто запрос, как это:

SELECT o_orderdate, count(o_orderdate) AS order_count 
FROM h_orders 
WHERE rownum <= 5 
GROUP BY o_orderdate