SQL Server:带日期的递归CTE-类型不匹配

时间:2019-12-12 18:17:19

标签: sql-server tsql

考虑在日期上创建带有递归CTE的日历。但是,一旦运行它,我将收到以下错误:

  

递归查询“ cte_days”的列“ ddmmyyyy”中的锚点与递归部分之间的类型不匹配

代码:

WITH cte_days(n, weekd, ddmmyyyy) AS
(   
    SELECT 
        0, DATENAME(DW, '09-03-1983'), CONVERT(varchar, '09-03-1983', 10)
    UNION ALL   
    SELECT 
        0 + 1, DATENAME(weekday, DATEADD(day, 1, '09-03-1983')), DATEADD(day, 1, '09-03-1983')                      
    FROM 
        cte_days
    WHERE 
        n < 10
)   
SELECT * 
FROM cte_days

那时,我尝试在ddmmyyyy列中测试数据,该数据在中间运行两个SELECTS并被正确返回:

0   Saturday    1983-09-03 00:00:00.000
1   Sunday      1983-09-04 00:00:00.000 

使用日期列创建临时表并将两个值都粘贴在其中后,它也可以正常工作。

那么您可以帮助查找不匹配的内容吗?

谢谢。

4 个答案:

答案 0 :(得分:3)

“考虑在日期上创建带有递归CTE的日历。” 老实说,我建议在rCTE上使用Tally。 rCTE实际上比Tally慢得多。这应该足以让您入门:

DECLARE @StartDate date = '19830309';

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (100) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1, N N2, N N3) --Add more Cartisian Joins and increase value of TOP to get more rows
SELECT I,
       DATENAME(WEEKDAY,DATEADD(DAY, I, @StartDate)) AS DayName,
       DATEADD(DAY, I, @StartDate) AS DyDate
FROM Tally;

答案 1 :(得分:1)

SQL Server对字符串类型很挑剔。但我建议您将注意力集中在CTE中的日期上,然后再进行转换:

WITH cte_days(n, dte) AS (
      SELECT 0, CONVERT(date, '19830309')
      UNION ALL
      SELECT n+1, DATEADD(day, 1, dte)
      FROM cte_days
      WHERE n < 10
     )
SELECT n, DATENAME(weekday, dte), CONVERT(VARCHAR(255), dte, 10)
FROM cte_days;

答案 2 :(得分:0)

使用CAST函数代替CONVERT也有帮助:

WITH cte_days(n, weekd, ddmmyyyy) 
AS (    
 SELECT 0, DATENAME(DW, '09-03-1983'),CAST(CAST('09-03-1983' AS DATE) AS DATETIME)       
        UNION ALL   
 SELECT n+1, DATENAME(weekday, DATEADD(day, 1, '09-03-1983')), DATEADD(day, 1, '09-03-1983')                        
 FROM cte_days                                                                  
    WHERE n < 10                                                                        
)   
SELECT * FROM cte_days 

答案 3 :(得分:0)

将“从n <10开始的cte_days天数”移到CTE之外是可以的。

    --Your Code: 
WITH cte_days(n, weekd, ddmmyyyy) AS
(   
    SELECT 
        0, DATENAME(DW, '09-03-1983'), CONVERT(varchar, '09-03-1983', 10)
    UNION ALL   
    SELECT 
        0 + 1, DATENAME(weekday, DATEADD(day, 1, '09-03-1983')), DATEADD(day, 1, '09-03-1983')                      
    FROM 
        cte_days
    WHERE 
        n < 10
)   
SELECT * 
FROM cte_days

工作代码:

    WITH cte_days(n, weekd, ddmmyyyy) AS
(   
    SELECT 
        0, DATENAME(DW, '09-03-1983'), CONVERT(varchar, '09-03-1983', 10)
    UNION ALL   
    SELECT 
        0 + 1, DATENAME(weekday, DATEADD(day, 1, '09-03-1983')), DATEADD(day, 1, '09-03-1983')                      
)   
SELECT * 
FROM cte_days
    WHERE 
        n < 10

以上返回以下结果:

n   weekd   ddmmyyyy
0   Saturday    1983-09-03 00:00:00.000
1   Sunday  1983-09-04 00:00:00.000