Oracle SQL: Как изменить запрос, чтобы получать только результаты в течение определенного периода времени?

#sql #oracle-sqldeveloper

Вопрос:

Я использую это утверждение в Oracle SQL Developer

 select to_char(time,'DD/MM/YY hh24'),count(column) as xyz from table
where to_char(time,'DD/MM/YY')>= '08/04/21'
and to_char(time,'DD/MM/YY')<= '09/04/21'
and column='xyz'
group by to_char(time,'DD/MM/YY hh24')
order by to_char(time,'DD/MM/YY hh24');
 

То, что я ожидаю, — это результат/таблица, в которой результат упорядочен по времени в порядке возрастания (начиная с самого раннего часа 08/04/21 и заканчивая последним 09/04/21 . Я бы ожидал только записей на несколько дней 08/04/21 и 09/04/21 . Вместо этого я получаю результат, в котором также указаны другие даты, такие как 09/02/21 или 08/12/20 .

Как я могу изменить свой запрос?

Комментарии:

1. Можете ли вы включить некоторые примеры данных для своей таблицы?

2. Для результирующей таблицы или для фактической таблицы, для которой я выполняю запрос?

3. Ну и то и другое, но, по крайней мере, примеры данных для исходной таблицы.

4. вы можете изменить все форматы дат, которые вы возвращаете, на «ГГГГ/ММ/ДД», в противном случае они не сравниваются в соответствии с порядком дат. Кроме того, ваше использование YY чревато проблемой Y2K

Ответ №1:

Вы преобразуете свои собственные значения дат в строки (с двузначными годами!), а затем сравниваете эти строки. Строка «08/12/20» меньше, чем строка «09/04/21».

Сравните свои даты с другими датами, что проще в виде литералов:

 select to_char(trunc(time, 'HH'), 'DD/MM/YY HH24'), count(column) as xyz
from table
where time >= date '2021-04-08'
and time < date '2021-04-10'
and column='xyz'
group by trunc(time, 'HH')
order by trunc(time, 'HH');
 

Я использовал trunc() для удаления/обнуления частей минуты и секунды, что означает, что вы можете затем сгруппировать и упорядочить по этому значению; и просто преобразовать в строку для отображения в последний момент.

Я также преобразовал to_char(time,'DD/MM/YY')<= '09/04/21' time < date '2021-04-10' , а не time < date '2021-04-09' как ваша версия, все данные с 9 — го числа; что может быть или не быть тем, что вы намеревались-возможно, вы пытались получить один день.

db<>демонстрация скрипки

Комментарии:

1. Большое спасибо! Это решило проблему. Но один вопрос: я хотел включить 09/04/2021. Но при использовании and creationtime <= date '2021-04-09' строк за 09/04/21 они не включаются при использовании вашего решения. Почему это так?

2. Потому date '2021-04-09' что 9-го числа полночь, т. е. 2021-04-09 00:00:00; поэтому все, что происходит позже полуночи, не совпадает, даже 2021-04-09 00:00:01. Вот почему я перешел на < date '2021-04-10' — это включает в себя все, вплоть до полуночи 10 — го, но не включая ее, — и, таким образом, включает в себя все время 9-го.

3. Хорошо, большое спасибо за ваше объяснение и помощь 🙂

Ответ №2:

Предполагая , что time это относится к типу данных date , вы не хотите делать to_char это в своем where предложении или в своем order by . Как написано, вы выполняете сравнение строк, а не сравнение дат, поэтому вы получаете строки, в которых to_char(time строка сортируется в алфавитном порядке между двумя значениями, а не строки, в которых дата находится между двумя датами. Сравните с литералами даты или выполните явные to_date вызовы строковых литералов

Держу пари, что ты действительно хочешь чего-то подобного

 select trunc(time, 'HH24'),count(column) as xyz 
  from table
 where time >= date '2021-08-04'
   and time <= date '2021-09-04'
   and column='xyz'
 group by trunc(time, 'HH24')
 order by trunc(time, 'HH24');