SQL 根据时间查询

SQL query based on the time

下面是table:

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' = '112015' 的入场时间,出场时间超过 24 小时的人。还有

2) 特定月份没有外出时间的人 'mmyyyy' = '112015'.

示例输出:

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

S801C       28-NOV-15 08.00.00  -

这应该有效。

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”转换为日期值(默认为该月的第一天)并使用与转换后的日期和一个月外的部分封闭范围比较将启用此类索引。

1) who have out-time greater than 24 hrs based on the in-time for the 'mmyyyy' = '112015'

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

2) who have no out-time for the particular month '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 列上的任何常规索引,在性能方面效率不高。更好的方法是使用 range 条件。

例如,

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