【问题标题】:Making a subquery with a set of dates (sundays) between two points在两点之间使用一组日期(星期日)进行子查询
【发布时间】:2018-06-28 16:53:30
【问题描述】:

我需要用一组日期形成几个子查询,只包括两个设置点之间的星期天,例如 01.04.2018 和 30.06.2018 之间。

首先想到的是这样的:

SELECT '01.04.2018' STARTDATE FROM DUAL
UNION ALL
SELECT '08.04.2018' STARTDATE FROM DUAL
...

但它看起来不是很优雅。有没有更简单的方法来实现我的需要?

【问题讨论】:

  • 您的意思是您只想识别两个日期之间的星期日日期吗?
  • 并发布表结构和列日期/时间?或者只是日期,你想要唯一的日期(如果包括时间)?
  • 你有合适的日期维度表吗?
  • 这会更容易通过引用日期维度表,只需拉回当天是星期天且介于目标日期之间的记录
  • @jimmy8ball 这不是 SQL Server 问题。

标签: sql oracle optimization


【解决方案1】:

你可以使用:

SQL Fiddle

查询 1

SELECT NEXT_DAY( DATE '2018-04-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
CONNECT BY
       NEXT_DAY( DATE '2018-04-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= DATE '2018-06-30'

Results

|            STARTDATE |
|----------------------|
| 2018-04-01T00:00:00Z |
| 2018-04-08T00:00:00Z |
| 2018-04-15T00:00:00Z |
| 2018-04-22T00:00:00Z |
| 2018-04-29T00:00:00Z |
| 2018-05-06T00:00:00Z |
| 2018-05-13T00:00:00Z |
| 2018-05-20T00:00:00Z |
| 2018-05-27T00:00:00Z |
| 2018-06-03T00:00:00Z |
| 2018-06-10T00:00:00Z |
| 2018-06-17T00:00:00Z |
| 2018-06-24T00:00:00Z |

这种结构是否总是至少返回一行?如果我添加一个附加条件 NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7 应该小于 SYSDATE 它仍然返回大于 SYSDATE 的第一行。

是的,如果只在CONNECT BY 子句中执行过滤,分层查询将始终返回一行(因为它只会在尝试将一行连接到其父行并且需要生成至少一个时才检查它父母首先这样做):

SELECT NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
CONNECT BY
       NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= LEAST(
              SYSDATE, -- DATE '2018-06-29'
              DATE '2018-07-30'
            )

结果

|            STARTDATE |
|----------------------|
| 2018-07-01T00:00:00Z | -- Greater than SYSDATE

但是如果你添加一个WHERE 子句(而不是在CONNECT BY 子句中过滤),那么它可以返回零行:

SELECT NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
WHERE  NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= SYSDATE
CONNECT BY
       NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= DATE '2018-07-30'

结果

No data found.

【讨论】:

  • 不仅解决了问题,还给我介绍了SQL中的递归:)谢谢!
  • 这种结构是否总是至少返回一行?如果我添加一个附加条件 NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7 应该小于 SYSDATE 它仍然返回大于 SYSDATE 的第一行。
  • @User24112017 更新
【解决方案2】:

蛮力方法是仅生成整个日期范围,然后对其进行过滤以仅保留星期日:

WITH cte AS (
    SELECT TRUNC (date '2018-06-30' - ROWNUM) dt
    FROM DUAL CONNECT BY ROWNUM < 100
)

SELECT * FROM cte WHERE TO_CHAR(dt, 'DAY') = 'SUN'

【讨论】:

  • 为什么正好是 99 行?如果我想要 2 年的周日会怎样?为什么不使用 OP 的日期边界而不是任意幻数?
  • @MT0 我没有你的 Oracle 技能。这是我能做的最好的了。
  • CONNECT BY TRUNC (date '2018-06-30' - ROWNUM) &gt;= DATE '2018-04-01' 将摆脱幻数并使用 OP 的日期边界。
猜你喜欢
  • 2017-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 2019-12-29
  • 1970-01-01
相关资源
最近更新 更多