子CTE或嵌套模型

时间:2014-04-23 10:31:02

标签: sql sql-server common-table-expression

我有一个月份和年份的字符串变量。这可以用逗号分隔多个。我需要在字符串

中获取所有月份的所有日期

例如:如果我的字符串有' 2014-01,2014-02'我需要在1月份的所有日子以及2月份的所有日期返回01-01-2014,02-01-2014等。

我试过以下

DECLARE  @myString as NVARCHAR(2000)     = '2014-03,2014-04'  
;with cte1
as (
    SELECT 
    CAST(        
      CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +        
      RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +        
      RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)         
   AS DATE) AS StartDate
    ,CONVERT(DATE,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,CAST(        
      CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +        
      RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +        
      RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)         
   AS DATETIME))+1,0))) AS EndDate
    FROM dbo.Split(myString , ',')    

),
cte2
AS
(
    SELECT StartDate, EndDate FROM cte1 

    UNION ALL

    SELECT CONVERT(DATE, DATEADD(DAY,1 , StartDate)), CONVERT(DATE, DATEADD(DAY,1 , StartDate)) FROM cte2  
    WHERE CONVERT(DATE, DATEADD(DAY,1 , StartDate)) < EndDate
)


SELECT * FROM cte2

在第一个cte中,我将返回2行,其中包含月份的开始日期和月份的结束日期。所以我需要循环第一个cte

的每一行的所有日子

我有两个单独的查询

- 获取月份开始和结束日期

;with cte1
as (
    SELECT 
    CAST(        
      CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +        
      RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +        
      RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)         
   AS DATE) AS StartDate
    ,CONVERT(DATE,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,CAST(        
      CAST(SUBSTRING(Data, 0, 5) AS VARCHAR(4)) +        
      RIGHT('0' + CAST(SUBSTRING(Data, 6, 2) AS VARCHAR(2)), 2) +        
      RIGHT('0' + CAST(1 AS VARCHAR(2)), 2)         
   AS DATETIME))+1,0))) AS EndDate
    FROM dbo.Split(@CompareMonths, ',')    

)

- 获取开始日期和结束日期(当月)之间的所有日期

Declare @startdate date = CONVERT(DATE, DATEADD(dd, -DAY(DATEADD(MONTH, 0, GETDATE())) + 1, DATEADD(MONTH, 0, GETDATE())))     
 Declare @endDate date = DATEADD(DAY, -DAY(DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))    

;With cte    
as    
(    
 SELECT @startdate sDate    
 UNION All    
 SELECT DATEADD(day,1,sDate) FROM cte WHERE DATEADD(day,1,sDate) <= @endDate    
)  
select * from cte

我需要加入这两个概念,以便从字符串中得到我过去所有月份的所有日子

1 个答案:

答案 0 :(得分:2)

借助数字表和splistring函数。

SQL Fiddle

MS SQL Server 2012架构设置

create table dbo.Number(N int primary key);

go

insert into dbo.Number(N)
select top(11000) row_number() over(order by 1/0) - 1
from sys.all_objects as o1, sys.all_objects as o2

go

create function [dbo].[SplitString](@List nvarchar(max), @Delimiter nvarchar(255)) returns table
with schemabinding
as
return
(
  select substring(@List, N, charindex(@Delimiter, @List + @Delimiter, N) - N) as Item
  from dbo.Number
  where N <= convert(int, len(@List)) and
        substring(@Delimiter + @List, N, len(@Delimiter)) = @Delimiter
);

查询1

declare @S nvarchar(max) = '2014-01,2014-02'

select T2.D
from dbo.SplitString(@S, N',') as S
  cross apply (select cast(S.Item+'-01' as date)) as T1(D)
  cross apply (
              select dateadd(day, N.N, T1.D)
              from Number as N
              where N between 0 and datediff(day, T1.D, eomonth(T1.D))
              ) as T2(D)

<强> Results

|          D |
|------------|
| 2014-01-01 |
| 2014-01-02 |
| 2014-01-03 |
| 2014-01-04 |
| 2014-01-05 |
| 2014-01-06 |
| 2014-01-07 |
| 2014-01-08 |
| 2014-01-09 |
| 2014-01-10 |
| 2014-01-11 |
| 2014-01-12 |
| 2014-01-13 |
| 2014-01-14 |
| 2014-01-15 |
| 2014-01-16 |
| 2014-01-17 |
| 2014-01-18 |
| 2014-01-19 |
| 2014-01-20 |
| 2014-01-21 |
| 2014-01-22 |
| 2014-01-23 |
| 2014-01-24 |
| 2014-01-25 |
| 2014-01-26 |
| 2014-01-27 |
| 2014-01-28 |
| 2014-01-29 |
| 2014-01-30 |
| 2014-01-31 |
| 2014-02-01 |
| 2014-02-02 |
| 2014-02-03 |
| 2014-02-04 |
| 2014-02-05 |
| 2014-02-06 |
| 2014-02-07 |
| 2014-02-08 |
| 2014-02-09 |
| 2014-02-10 |
| 2014-02-11 |
| 2014-02-12 |
| 2014-02-13 |
| 2014-02-14 |
| 2014-02-15 |
| 2014-02-16 |
| 2014-02-17 |
| 2014-02-18 |
| 2014-02-19 |
| 2014-02-20 |
| 2014-02-21 |
| 2014-02-22 |
| 2014-02-23 |
| 2014-02-24 |
| 2014-02-25 |
| 2014-02-26 |
| 2014-02-27 |
| 2014-02-28 |

Ref: Split strings the right way – or the next best way