2015-12-16 2 views
-1

Ниже приводится таблица:SQL запрос на основе времени

ID_NO  in_time     out_time 
S162Z  02-JUL-10 08.00.00 02-JUL-10 16.00.00 
S162Z  07-OCT-10 10.00.00 08-OCT-10 13.00.00 
S162Z  23-FEB-11 08.00.00 23-FEB-11 16.00.00 
S162Z  01-FEB-14 09.00.00 12-FEB-14 18.00.00 
S162Z  26-NOV-15 08.00.00 27-NOV-15 10.00.00 
S682D  03-NOV-14 08.00.01 03-NOV-14 08.00.01 
S801C  28-NOV-15 08.00.00 - 
S801C  07-OCT-10 10.00.00 - 
S801C  23-FEB-11 08.00.00 - 

Я хочу, чтобы найти те, которые имеют id_no из времени более чем на 24 часов, основанных на IN_time в определенный месяц.

Как я хочу, чтобы найти эти идентификаторы основаны на указанных ниже условиях

1), которые вне времени больше, чем за 24 часов на основе по времени для «mmyyyy» = «112015». а также

2) у кого нет времени на конкретный месяц «mmyyyy» = '112015'.

Пример вывода:

S162Z 26-NOV-15 08.00.00 27-NOV-15 10.00.00

S801C  28-NOV-15 08.00.00 - 
+0

Чтобы дать вам некоторую обратную связь, что формат '' in_time' и out_time' столбцов? Вы можете просто принять разницу между этими столбцами, как только вы перейдете к проблеме форматирования. –

+0

@TimBiegeleisen Время и время выхода в формате даты. –

+0

... и что вы пробовали? – Trent

ответ

2

1), которые имеют вне времени больше, чем за 24 часов на основе в времени для «mmyyyy» = «112015»

Вы можете использовать TO_CHAR сравнить MMYYYY, а затем вычесть out_time и in_time, чтобы проверить, превышает ли разность 24 hours т.е. 1 день.

2) у кого нет времени на определенный месяц «mmyyyy» = '112015'.

Это должно быть простое условие IS NULL.

Предполагая, что тип данных вашей in_time и out_time колонки быть ДАТА, ваш фильтр предиката будет:

WHERE TO_CHAR(in_time, 'MMYYYY') = TO_CHAR(out_time, 'MMYYYY') 
AND out_time      > in_time + 1 
OR out_time      IS NULL; 

Рабочая Демо:

SQL> WITH sample_data AS(
    2 SELECT 1 ID, SYSDATE -1 in_time, SYSDATE + 2/24 out_time FROM dual UNION ALL 
    3 SELECT 1, SYSDATE -10,  SYSDATE + 2/24 FROM dual UNION ALL 
    4 SELECT 2, SYSDATE -1/24,  SYSDATE + 2/24 FROM dual UNION ALL 
    5 SELECT 2, SYSDATE -1/24,  NULL FROM dual 
    6 ) 
    7 -- end of sample_Data mimicking a real table 
    8 SELECT * 
    9 FROM sample_data 
10 WHERE TO_CHAR(in_time, 'MMYYYY') = TO_CHAR(out_time, 'MMYYYY') 
11 AND out_time      > in_time + 1 
12 OR out_time      IS NULL; 

     ID IN_TIME    OUT_TIME 
---------- -------------------- -------------------- 
     1 15-DEC-2015 10:49:27 16-DEC-2015 12:49:27 
     1 06-DEC-2015 10:49:27 16-DEC-2015 12:49:27 
     2 16-DEC-2015 09:49:27 

Если вы хотите ограничить это в конкретный месяц и год, просто добавьте еще одно условие:

AND TO_CHAR(in_time, 'MMYYYY') = '112015' 

Как Страж указывает, используя TO_CHAR на колонке будет подавлять любой обычный индекс на in_time колонке, не эффективно с точки зрения производительности. Лучшим способом было бы использовать диапазон.

Например,

SQL> WITH sample_data AS(
    2  SELECT 1 ID, SYSDATE -1 in_time, SYSDATE + 2/24 out_time FROM dual UNION ALL 
    3  SELECT 1, SYSDATE -10,  SYSDATE + 2/24 FROM dual UNION ALL 
    4  SELECT 2, SYSDATE -1/24,  SYSDATE + 2/24 FROM dual UNION ALL 
    5  SELECT 2, SYSDATE -1/24,  NULL FROM dual 
    6  ) 
    7 -- end of sample_Data mimicking a real table 
    8 SELECT * 
    9 FROM sample_data 
10 WHERE in_time >= to_date('112015','mmyyyy') 
11 AND in_time < add_months(to_date('112015','mmyyyy'), 1) 
12 AND (out_time > in_time + 1 
13 OR out_time IS NULL); 

     ID IN_TIME    OUT_TIME 
---------- -------------------- -------------------- 
     1 15-DEC-2015 11:38:20 16-DEC-2015 13:38:20 
     1 06-DEC-2015 11:38:20 16-DEC-2015 13:38:20 
     2 16-DEC-2015 10:38:20 
+0

Преобразование in_time в строковое значение не позволит БД использовать любые индексы, не основанные на функциях, которые могут существовать в столбце in_time. В общем случае лучше не изменять тип данных столбца таблицы, а вместо этого изменять типы данных констант или переменных, с которыми вы их сравниваете. В этом случае это означает использование некоторой формы ранжированного сравнения, а не проверки равенства. – Sentinel

+0

@ Sentinel Согласен. Я сам бы предложил условие диапазона, чтобы использовать любой регулярный индекс в столбце in_time. Однако важно было сосредоточиться на логике. Нет, что вы упомянули об этом, я бы отредактировал ответ, чтобы добавить часть производительности. –

+0

@LalitKumarB благодарит за такое ясное объяснение –

0

Это должно работать.

select * 
    from your_table 
where to_date('112015','mmyyyy') <= in_time 
    and in_time < to_date('112015','mmyyyy') + interval '1' month 
    and (out_time is null or in_time - out_time > 1); 

Если есть какие-либо указатели на колонке IN_time, лучше не преобразовать его в строку для сравнения с вашей «112015» строки. Вместо этого преобразование «112015» в значение даты (которое по умолчанию относится к первому из месяца) и использование частично закрытого диапазона сравнения с преобразованной датой и одним месяцем позволит использовать такой индекс.