SQL查询基于时间

时间:2015-12-16 04:55:00

标签: sql oracle date-formatting date-arithmetic

以下是表格:

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  -

我想根据特定月份的in_time找到那些时间超过24小时的id_no。

就像我想根据以下条件找到那些ID

1)根据“mmyyyy”的及时时间超过24小时的人员。 =' 112015'。还有

2)谁没有特定月份的退出时间' mmyyyy' =' 112015'。

示例输出:

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

S801C       28-NOV-15 08.00.00  -

2 个答案:

答案 0 :(得分:2)

  

1)根据“mmyyyy”的及时时间超过24小时的人员。 =' 112015'

您可以使用 TO_CHAR 来比较MMYYYY,然后减去out_timein_time以检查差异是否大于24 hours,即1一天。

  2)谁没有特定月份的退出时间' mmyyyy' =' 112015'。

这应该是一个简单的IS NULL条件。

假设您的in_timeout_time列的数据类型为 DATE ,您的过滤谓词将为:

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'

正如Sentinel所指出的,在列上使用 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

答案 1 :(得分: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列中有任何索引,最好不要将其转换为字符串,以便与您的&#11; 112015&#39;进行比较。串。而是转换&#39; 112015&#39;到日期值(默认为该月的第一个)并使用部分关闭的范围与转换日期和一个月的比较将使得能够使用这样的索引。