如何在SQL中生成没有临时表的日期范围序列

时间:2017-06-07 17:52:12

标签: sql-server oracle

我想将一些代码行从Oracle查询转换为MSSQL。

   WITH DATE_MONTHS AS
(
  SELECT TO_CHAR(ADD_MONTHS(TO_DATE(TRUNC(TO_DATE(P_REQUIRED_DATE),'MON')), - LEVEL 
  +1),'DD-MON-YYYY') MONTHS FROM DUAL
  CONNECT BY LEVEL <= P_MONTH_RANG
)
SELECT * from DATE_MONTHS

参数:

  • P_REQUIRED_DATE即sysdate
  • P_MONTH_RANG即4

结果:

  • 2017年1月5日
  • 2017年1月4日
  • 2017年1月3日
  • 2017年1月2日

2 个答案:

答案 0 :(得分:3)

一种简单的方法是使用计数表并生成如下所示:

declare @P_Required_Date date = '2015-05-01'
declare @P_Month_Rang int = 4

Select top (@P_Month_Rang) Dts = DateAdd(month, -(Row_Number() over(order by (Select NULL))-1), @P_Required_Date) from 
        master..spt_values s1, master..spt_values s2

输出如下:

    +------------+
    |    Dts     |
    +------------+
    | 2015-05-01 |
    | 2015-04-01 |
    | 2015-03-01 |
    | 2015-02-01 |
    +------------+

您的CTE方法:

declare @P_Required_Date date = '2015-05-01'
declare @P_Month_Rang int = 4

;with Date_Months as
(
    Select @P_Required_Date as Dates, 1 as Levl

    Union all

    Select DateAdd(MONTH,-1, Dates), Levl+1 as Levl  from Date_Months
        where Levl < @P_Month_Rang
)
Select convert(varchar(10), dates, 103) from Date_Months

要转换为dd-mm-yyyy格式,一种方法是使用选项103进行转换或使用Format。

答案 1 :(得分:1)

使用Stacked Ctes的另一个选项

declare @fromdate date = '20150501';
declare @months int = 4;

;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
  select top (@months) 
      [Date]=convert(date,dateadd(month,-(row_number() over(order by (select 1))-1),@fromdate))
  from n as deka cross join n as hecto cross join n as kilo cross join n as tenK
  order by [Date] desc
)
select [Date] = convert(char(10),[date],105)
from dates;

rextester演示:http://rextester.com/UUW2271

返回:

+------------+
|    Date    |
+------------+
| 01-05-2015 |
| 01-04-2015 |
| 01-03-2015 |
| 01-02-2015 |
+------------+

基准&amp;性能测试:Generate a set or sequence without loops - 2 - Aaron Bertrand