【问题标题】:Connect by level for SQL Server 2008 like OracleSQL Server 2008 的按级别连接,如 Oracle
【发布时间】:2012-07-17 21:15:27
【问题描述】:
nDays := Round( dEndTime - dStartTime ) + 1; 

For i in 1..7 Loop
 nDay := i + 1;
    if i = 7 Then
      nDay := 1;
    End If;

SELECT To_Date(To_Char((dStartTime+Level-1),'DD.MM.YYYY')||' 00:00','DD.MM.YYYY HH24:MI'),
To_Date(To_Char((dStartTime+Level-1),'DD.MM.YYYY')||' 23:59','DD.MM.YYYY HH24:MI')
FROM DUAL
WHERE To_Char( dStartTime + Level -1 , 'd' ) =  To_Char(nDay)
CONNECT BY Level <= nDays;

End Loop;

输出:

22-JUL-12
23-JUL-12
18-JUL-12
19-JUL-12
20-JUL-12
21-JUL-12

我需要将此查询转换为 SQL Server 2008,请帮助找到相同的解决方法......

我已经尝试使用 nDay 从 1 到 7 进行单个查询的上述输出.....

【问题讨论】:

  • 看看this SO question,您可以在SQL server 中使用CTE,类似于Oracle 的connect by(递归CTE 现在是ANSI 标准的层次结构移动方式)。

标签: sql oracle sql-server-2008


【解决方案1】:

您可以使用递归 CTE 来做到这一点。但是,这种语法可能很难记住,所以当我需要一些项目时,我会执行以下操作:

select *
from (select row_number() over (order by (select NULL)) as seqnum
      from information_schema.columns
     ) t
where seqnum < <value>

可以使用任何表格。我只是放入INFORMATION_SCHEMA.columns表,因为它很简单,一般有几十或几百行。

您的输出与查询不匹配。下面生成两个值之间的所有日期,这些值相当接近,这里是一个例子:

declare @dstarttime date = '2012-07-11', @dendtime date=  '2012-07-13';
with const as (select @dstarttime as dStartTime, @dendtime as dendTime)
SELECT DATEADD(d, seqnum - 1, dStartTime)
FROM (select *
      from (select row_number() over (order by (select NULL)) as seqnum, const.*
            from information_schema.columns cross join const
           ) t
      where seqnum <= DATEDIFF(d, dStartTime, dendTime) + 1
     ) t

正如我所说,您也可以使用递归 CTE 来执行此操作,或者,如果有的话,可以使用日历表。

【讨论】:

  • 感谢您的 rpl Gordon Linoff,但根据您给定的解决方案,我已经使用了它,下面也提供与您相同的输出......,但我希望按照我给定的输出...... WITH DateRange(dt) AS (SELECT CONVERT(datetime, '2009-01-01') dt UNION ALL SELECT DATEADD(dd,1,dt) dt FROM DateRange WHERE dt
猜你喜欢
  • 2015-03-19
  • 2013-05-07
  • 2019-05-22
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多