【问题标题】:Oracle SQL - Data from previous week (Sunday to Saturday) regardless of when it's runOracle SQL - 前一周(周日至周六)的数据,无论何时运行
【发布时间】:2017-03-17 15:31:26
【问题描述】:

我希望在 Oracle 中返回从周日开始到周六结束的最后一周的数据。这需要能够在一周中的任何一天运行。

所以我知道这在 SQL Server 中是可能的,因为我有报告执行完全相同的操作:-

SET @startdate = DATEADD(wk, -1, DATEADD(wk, DATEDIFF(wk, 0,getdate()), -1))
SET @enddate = DATEADD(wk, DATEDIFF(wk, 0, getdate()), -1)

今天是 3 月 17 日星期五,上面将返回 3 月 5 日星期日和 3 月 11 日星期六之间的数据。

我想在 Oracle 中做同样的事情。到目前为止,我所看到的所有地方都返回了这样的结果:-

SELECT TRUNC (SYSDATE) - (SELECT TO_CHAR (SYSDATE, 'D') FROM DUAL),
       TRUNC (SYSDATE) - (SELECT TO_CHAR (SYSDATE, 'D') + 1 FROM DUAL)
FROM DUAL

或者

SELECT SYSDATE AS TODAYS_DATE, 
       NEXT_DAY (SYSDATE - 7, 'SAT') AS PREV_SATURDAY,
       NEXT_DAY (SYSDATE - 7, 'SUN') AS PREV_SUNDAY
FROM DUAL

我试图避免使用任何 'sysdate-7' 类型的代码,因为在这种情况下这非常笨拙 - 任何人都可以提供帮助吗?

谢谢

【问题讨论】:

  • sysdate 是否比 MSSQL 代码更笨拙?
  • 笨拙?在什么方面?
  • 关于我需要在一周中的每一天编码。

标签: sql oracle date-arithmetic


【解决方案1】:

如果在任何给定时间点,“前一周”是指在周日开始的最近一个午夜结束的 7 天时间段,那么这样的事情应该有效:

with inputs (dt) as (
       select sysdate     from dual union all
       select sysdate + 1 from dual union all
       select sysdate + 2 from dual union all
       select sysdate + 3 from dual
     )
-- end of test data; SQL solution begins below this line
select to_char(dt, 'Dy dd-Mon-yyyy hh:mi AM') as dt,
       trunc(dt + 1, 'iw') - 8 as prev_wk_start,
       trunc(dt + 1, 'iw') - 1 as prev_wk_end
from   inputs;

DT                         PREV_WK_START         PREV_WK_END
------------------------   -------------------   -------------------
Fri 17-Mar-2017 10:58 AM   03/05/2017 00:00:00   03/12/2017 00:00:00
Sat 18-Mar-2017 10:58 AM   03/05/2017 00:00:00   03/12/2017 00:00:00
Sun 19-Mar-2017 10:58 AM   03/12/2017 00:00:00   03/19/2017 00:00:00
Mon 20-Mar-2017 10:58 AM   03/12/2017 00:00:00   03/19/2017 00:00:00

注意:每当我们使用时间间隔时,我们必须确定是否包含端点。在大多数情况下,最好的(也是最常用的)约定是包括开始日期/时间,而不包括结束日期/时间。上面的查询与这个解释是一致的。如果针对 date '2017-03-19' 之类的输入运行查询,即星期日开始的午夜,则查询将返回恰好在该日期和时间结束的星期。所有这些“前一周”都严格在输入日期/时间之前,因为一周的结束点不包括在“一周间隔”中。

【讨论】:

  • 谢谢 - 这正是我所需要的。 ORD_DATE >= TRUNC(SYSDATE + 1, 'IW') - 8 AND ORD_DATE
  • @LuckySevens - 在大多数情况下,最后一个不等式应该是
【解决方案2】:

使用TRUNC( date_value, 'IW' ) 独立于NLS_TERRITORYNLS_DATE_LANGUAGE 会话参数:

SELECT SYSDATE                                   AS TODAYS_DATE,
       TRUNC( SYSDATE, 'IW' )                    AS MONDAY_OF_THIS_ISO_WEEK,
       TRUNC( SYSDATE, 'IW' ) - INTERVAL '2' DAY AS PREV_SATURDAY,
       TRUNC( SYSDATE, 'IW' ) - INTERVAL '8' DAY AS PREV_SUNDAY
FROM   DUAL;

输出

TODAYS_DATE         MONDAY_OF_THIS_ISO_ PREV_SATURDAY       PREV_SUNDAY       
------------------- ------------------- ------------------- -------------------
2017-03-17 15:45:25 2017-03-13 00:00:00 2017-03-11 00:00:00 2017-03-05 00:00:00

【讨论】:

  • 如果“上一周”是指从周日开始的午夜开始到正好 7 天后结束的 7 天时间段(这似乎是一个合理的定义),那么这个解决方案就行不通了,因为它会在下午 3 点给出相同的结果。周六和次日上午 10 点(周日);这些日期/时间的“前一周”不一样。公平地说,在您的解决方案中,您没有将任何内容“标记”为“前一周”——您只有 prev_saturday 等,但在我给出的两个示例中,即使“prev_saturday”也不相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-16
相关资源
最近更新 更多