【问题标题】:Query date and specific time in the where clause在where子句中查询日期和具体时间
【发布时间】:2018-10-23 02:32:07
【问题描述】:

我正在寻求有关 Oracle SQL 的帮助。我需要在 where 子句中查询日期和时间,以根据当前日期查找班次数据。有 3 个班次,早上 5 点到下午 1 点,下午 1 点到晚上 9 点,晚上 9 点到早上 5 点(第二天早上。例如

SELECT 'T1' AS SHIFT, WORK_CENTER, SUM(CASE WHEN AQL='PASS' THEN 1 ELSE 0) END AS AQL_PASSED
FROM Z_INSPECTION_DEFECTS
WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL)  , ''DD-MON-YYYY HH:MI:SS '') AND
       DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 1:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH:MI:SS '')

我没有从这个查询中得到任何结果。日期时间字段是洛杉矶当地时间的时间戳。

【问题讨论】:

  • 您的查询混合了单字、双字和转义的单字,这有点令人困惑。您不需要来自双重的内部选择。会话时区是否也是 LA(因为您使用的是 current_date 而不是 sysdate)?
  • 没有会话时区是UTC。 date_time 字段已转换为洛杉矶时区,这就是我使用 Current_Date 的原因。

标签: sql oracle date oracle-sqldeveloper


【解决方案1】:

直接的问题是您正在查看凌晨 5 点之后和凌晨 1 点之前的时间,这在逻辑上意味着没有匹配项 - 因为没有时间可以同时满足两者。您可以改用 24 小时制:

WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL)  , ''DD-MON-YYYY HH24:MI:SS '') AND
       DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), ''13:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH24:MI:SS '')

但是还有其他方法可以获得这些,例如只是没有针对dual的查询:

WHERE DATE_TIME >= TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || '' 5:00:00 '', ''DD-MON-YYYY HH24:MI:SS '') AND
       DATE_TIME < TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || ''13:00:00 '', ''DD-MON-YYYY HH24:MI:SS '')

或使用截断和日期算术:

WHERE DATE_TIME >= TRUNC(CURRENT_DATE) + (5/24) AND
       DATE_TIME < TRUNC(CURRENT_DATE) + (13/24)

您确实需要在目标时区获得这些时间,例如:

WHERE DATE_TIME >= FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), ''America/Los_Angeles'') AND
       DATE_TIME < FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), ''America/Los_Angeles'')

您需要小心current_date,它在您当前会话时区中,sysdate 在服务器时区中。如果您的会话是 UTC,那么 current_date 可能不会给您您期望的那一天。

(我坚持使用转义单引号,因为这主要是您在问题中遇到的问题,这意味着您可能正在使用动态 SQL 运行它;是否需要是另一回事。如果您只是这样做在运行时提供周期偏移量,那么就不需要是动态的......)

您可以通过这些计算查看生成的时间:

select FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), 'America/Los_Angeles'),
       FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), 'America/Los_Angeles')
from dual;

FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(5/24)ASTIMESTAM FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(13/24)ASTIMESTA
------------------------------------------------- -------------------------------------------------
2018-10-22 05:00:00.000000000 AMERICA/LOS_ANGELES 2018-10-22 13:00:00.000000000 AMERICA/LOS_ANGELES

【讨论】:

  • 谢谢亚历克斯。你查询专业知识帮我解决了这个问题。我添加了 sysdate 而不是 current_date 以确保我得到正确的日期。再次感谢您对此的帮助。
  • 如何获得第三班时间。这是我有的,但没有结果。 WHERE DATE_TIME_START >= sys_extract_utc(cast(trunc(current_date) + 19/24 作为带时区的时间戳)) AND DATE_TIME_START
  • 19/24 是晚上 7 点而不是晚上 9 点;你似乎已经恢复到current_date。而且我不确定您为什么现在使用 UTC 时间 - 您是否在查询中适用于其他班次?除此之外,您确定有该时期的数据吗? (这似乎与这个问题和我的答案有很大不同......最好提出一个新问题,显示示例数据和适用于其他班次的查询,以及未找到数据的查询。)
  • 它完美地适用于第 1 班和第 2 班。这是第三班的 where 子句。我在晚上 11:59:59 之前得到数据,然后在上午 12 点之后没有数据 -----WHERE DATE_TIME_START >=sys_extract_utc(cast(trunc(current_date) + 21/24 as time stamp with time zone)) AND DATE_TIME_START
  • 这是我的问题的链接。stackoverflow.com/questions/53603707/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 2014-11-11
  • 1970-01-01
相关资源
最近更新 更多