【问题标题】:How to select records from January 1, 2021 to last week如何选择2021年1月1日到上周的记录
【发布时间】:2021-06-14 19:22:46
【问题描述】:

我想知道如何进行查询以选择从 21 年 1 月 1 日到上周的数据。我试着把它放在这样的日期过滤器中:

where start_date between TO_DATE('2021-01-01', 'yyyy-mm-dd') 
                     and TO_DATE('2021-06-13', 'yyyy-mm-dd')

但是我必须每周手动输入以更改结束日期,我想知道是否有更有效的方法来选择从今天开始直到上周的数据(意思是直到周日的数据),这样即使如果我从今天开始两天后运行查询,我只能得到从 1 月 1 日到上周日的数据?

【问题讨论】:

    标签: sql oracle date


    【解决方案1】:

    您可以TRUNCate SYSDATE 到 ISO 周的开始(通常是星期一),然后找到小于该值的值:

    SELECT *
    FROM   table_name
    WHERE  start_date >= DATE '2021-01-01'
    AND    start_date <  TRUNC( SYSDATE, 'IW' )
    

    这样做的好处是它独立于语言和位置,因此无论数据库或用户会话可能有任何设置,查询的行为都会完全相同。

    它还将获得所有周日可能出现的值(从00:00:0023:59:59)。

    如果您想要从当前年份开始的值(而不是来自2021-01-01 的固定下限),那么您可以使用:

    SELECT *
    FROM   table_name
    WHERE  start_date >= TRUNC( SYSDATE, 'YYYY' )
    AND    start_date <  TRUNC( SYSDATE, 'IW' )
    

    db小提琴here

    【讨论】:

    • 谢谢,但我如何在查询中构建它? “IW”是什么意思?
    • @comp_user 我在答案中给了你一个完整的查询和一个 dbfiddle 并演示了它的工作原理;当您问“如何在我的查询中构造它”时,我不确定您还想要什么。而且,正如我在第一行中所说,使用IW 格式模型截断到 ISO 周的开始(由 ISO8601 指定,并且始终是星期一的午夜)。您可以在互联网上搜索Oracle format models,如果需要,可以了解更多信息。
    • 有谁知道如何保持查询的灵活性,我知道上面的示例提供了从 21 年 1 月 1 日到最后一个星期日的数据,正如我在上面的原始问题中所问的那样,但有时我们有用户请求直到上周五或上周四才要求提供数据,而不是上周日,如果有人能给我一个可以理解的答案,我将不胜感激。谢谢
    • @comp_user 这超出了当前问题的范围;您应该将其作为一个新问题提出,而不是试图扩大现有问题的范围。但是您可以只找到 ISO 周的开始,然后减去 2 天以找到上周五的上限AND start_date &lt; TRUNC( SYSDATE, 'IW' ) - 2
    • 谢谢,我会在'sysdate和iw'上查找更多,似乎它们是有用的sql函数,而不是每次我们收到某个新请求时手动更改日期参数日期范围
    【解决方案2】:

    按照我的理解,您正在寻找行生成器。如果是这样,你在这里:

    首先,一些设置(正如我的数据库所说克罗地亚语);你不会那样做的:

    SQL> alter session set nls_date_format = 'dd.mm.yyyy, day';
    
    Session altered.
    
    SQL> alter session set nls_date_language = 'english';
    
    Session altered.
    

    查询自身,结果:

    SQL> select trunc(sysdate, 'yyyy') + level - 1 as datum
      2  from dual
      3  connect by level <= next_day(trunc(sysdate) - 7, 'sunday') - trunc(sysdate, 'yyyy') + 1
      4  order by datum;
    
    DATUM
    ---------------------
    01.01.2021, friday
    02.01.2021, saturday
    03.01.2021, sunday
    04.01.2021, monday
    05.01.2021, tuesday
    06.01.2021, wednesday
    07.01.2021, thursday
    08.01.2021, friday
    <snip>
    09.06.2021, wednesday
    10.06.2021, thursday
    11.06.2021, friday
    12.06.2021, saturday
    13.06.2021, sunday
    
    164 rows selected.
    
    SQL>
    

    如你所说:

    所以即使我从今天开始两天后运行查询,我也只能获得从 1 月 1 日到上周日的数据?

    让我们假设距离今天还有两天,即 2021 年 6 月 16 日(星期三)。我现在以特权用户身份连接,因此我可以更改系统的日期(你不会这样做):

    SQL> alter system set fixed_date = '16.06.2021';
    
    System altered.
    
    SQL> alter session set nls_date_language = 'english';
    
    Session altered.
    
    SQL> alter session set nls_date_format = 'dd.mm.yyyy, day';
    
    Session altered.
    
    SQL> select sysdate from dual;
    
    SYSDATE
    ---------------------
    16.06.2021, wednesday
    

    看到了吗?星期三。

    让我们再次尝试相同的查询:

    SQL> select trunc(sysdate, 'yyyy') + level - 1 as datum
      2  from dual
      3  connect by level <= next_day(trunc(sysdate) - 7, 'sunday') - trunc(sysdate, 'yyyy') + 1
      4  order by datum;
    
    DATUM
    ---------------------
    01.01.2021, friday
    02.01.2021, saturday
    03.01.2021, sunday
    04.01.2021, monday
    <snip>
    11.06.2021, friday
    12.06.2021, saturday
    13.06.2021, sunday
    
    164 rows selected.
    
    SQL>
    

    我觉得不错。

    【讨论】:

    • 谢谢,但是当我运行此查询时,我只能在周日下午 5 点之前获得数据,直到周日晚上 11:59 之前我都没有获得数据
    【解决方案3】:

    你可以使用下面的where子句-

    WHERE start_date BETWEEN TO_DATE('2021-01-01', 'yyyy-mm-dd') AND (TRUNC(SYSDATE) - TO_CHAR(SYSDATE, 'd'));
    

    【讨论】:

    • 这会根据数据库使用的区域(或在用户会话中设置)db<>fiddle 给出不同的结果
    • TO_CHAR(..., 'd') 的结果取决于当前用户会话NLS_TERRITORY 的设置,可能不可靠。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 2021-12-28
    • 2012-01-18
    • 2021-12-26
    • 2021-09-01
    • 1970-01-01
    相关资源
    最近更新 更多