Фильтрация SQL-запроса по строке и по диапазону дат

У меня есть индексированная по времени БД Oracle, которую я пытаюсь запросить по диапазону дат. Я также хочу сократить данные в запросе, чтобы не перегружаться слишком большим количеством данных.

Отдельный запрос даты (2352 строки за 0,203 с):

select oracle_time from t_ssv_soh_packets0
where oracle_time >= TIMESTAMP '2009-01-01 00:00:00' 
AND oracle_time <= TIMESTAMP '2009-01-31 00:00:00' 

Запрос на сокращение (1017 за 0,89 с):

select oracle_time from t_ssv_soh_packets0
where (rowid,0) in (select rowid, mod(rownum,50) from t_ssv_soh_packets0)

Когда я пытаюсь их объединить, это занимает вечность (48 строк за 32,547 с):

select oracle_time from t_ssv_soh_packets0
where oracle_time >= TIMESTAMP '2009-01-01 00:00:00' 
AND oracle_time <= TIMESTAMP '2009-01-31 00:00:00' 
AND (rowid,0) in (select rowid, mod(rownum,50) from t_ssv_soh_packets0)

Очевидно, что я делаю здесь что-то принципиально неправильное, но я не знаю, как еще сделать запрос по дате и уменьшить данные.


person Jason    schedule 14.12.2010    source источник


Ответы (4)


Вы оцениваете свою логику сокращения по строкам, которые не относятся к выбранному вами диапазону дат.

Примените логику сокращения к подзапросу, содержащему ваш диапазон дат.

ПОЗЖЕ: Вот что я имел в виду.

select oracle_time from (
  select oracle_time, rownum as limited_row_num
  from t_ssv_soh_packets0 
  where oracle_time >= TIMESTAMP '2009-01-01 00:00:00'  
  AND oracle_time <= TIMESTAMP '2009-01-31 00:00:00'  
) as time_range
where mod(limited_row_num,50) =  0
person Narveson    schedule 14.12.2010
comment
Ваш запрос не работает в Oracle, который является БД, которую я использую. Я не уверен, как перевести это в подзапрос, который нравится Oracle. Я думаю, что предложение «группировать по» является наиболее совместимым с БД. - person Jason; 17.12.2010
comment
Извиняюсь. Спасибо, что дал мне знать. - person Narveson; 17.12.2010

Избавьтесь от in

Зачем это использовать?:

select oracle_time from t_ssv_soh_packets0
where (rowid,0) in (select rowid, mod(rownum,50) from t_ssv_soh_packets0)

Ваше единственное условие - mod(rownum, 50)

select * from t where mod(rownum, 50)=0

последняя строка должна быть AND mod(rownnum,50)=0, а не самообъединением с in.

person nate c    schedule 14.12.2010
comment
Похоже, я по ошибке изменил имя моей таблицы «t_ssv_soh_packets0» на «table» в моем примере. Я пытаюсь получить эти данные, которые хранятся в t_ssv_soh_packets0. Ваш запрос не работает, и Oracle, похоже, считает, что проблема связана с линией соединения, в частности с «как пакеты». Я получаю сообщение об ошибке «отсутствует ключевое слово». - person Jason; 15.12.2010
comment
Oracle не всегда поддерживает «как», поскольку это не ANSI-жалоба. Приятно сказать, если вы используете Oracle в сообщении. - person nate c; 15.12.2010
comment
Этот запрос: select oracle_time from t_ssv_soh_packets0 where mod(rownum, 50)=0 выбирает 0 строк. - person Jason; 15.12.2010
comment
Я думал, что что-то вроде этого select t1.oracle_time from t_ssv_soh_packets0 t1 left join t_ssv_soh_packets0 t2 on mod(rownum, 100)=0 будет работать, но это действовало так, как будто мода даже не было. - person Jason; 15.12.2010

Вы также можете позволить Oracle выбрать случайную выборку из результата, применив SAMPLE():

SELECT oracle_time 
FROM t_ssv_soh_packets0
WHERE ...
SAMPLE(50)

Вернет случайным образом 50% процентов строк

person a_horse_with_no_name    schedule 15.12.2010
comment
Ваш комментарий был обрезан. У меня получилось следующее: SELECT oracle_time FROM t_ssv_soh_packets0 SAMPLE(50) WHERE oracle_time >= TIMESTAMP '2009-01-01 00:00:00' AND oracle_time <= TIMESTAMP '2009-01-31 00:00:00' Это вернуло 1182 строки за 0,1 с. - person Jason; 16.12.2010
comment
Странно, я отредактировал свой пример кода. По какой-то причине SO не любит WHERE и SAMPLE() - person a_horse_with_no_name; 16.12.2010

Благодаря обоим «Narveson» и «nate c» за указатели, я наконец понял это. Вот (вероятно, специфичный для Oracle) запрос, который я придумал:

select oracle_time from t_ssv_soh_packets0 where oracle_time >= TIMESTAMP '2009-01-01 00:00:00' AND oracle_time <= TIMESTAMP '2009-01-31 00:00:00' group by oracle_time, rownum having mod(rownum, 50)=0

Этот запрос возвращает 47 строк за 0,031 с. В исходном запросе времени было 2352 строки, так что это имеет смысл.

ORAFAQ помог мне найти окончательное решение.

person Jason    schedule 15.12.2010