首页 > 解决方案 > CTE 错误:锚点和递归部分之间的类型不匹配

问题描述

执行以下查询:

WITH cte AS (
    SELECT CAST('" + mindate+ "' as varchar(255))  as fdate
    UNION ALL
    SELECT CAST(DATEADD(day, 1, fdate) as date)
    FROM cte
    WHERE fdate < '" + tday+"'
)
SELECT COUNT(fdate) AS Fdate
FROM cte left join tbl_Attendence on cte.fdate = tbl_Attendence.Datess
where tbl_Attendence.Datess is null

但我以以下错误结束:

递归查询“cte”的“fdate”列中的锚点和递归部分之间的类型不匹配。

标签: sqlsql-servercommon-table-expression

解决方案


这是您的原始查询:

WITH cte AS 
(
    SELECT 
        CAST('" + mindate+ "' as varchar(255)) as fdate 

    UNION ALL 

    SELECT 
        CAST(DATEADD(day, 1, fdate) as date) 
    FROM 
        cte 
    WHERE 
        fdate < '" + tday+"' 
)
SELECT 
    COUNT(fdate) AS Fdate 
FROM 
    cte 
    left join tbl_Attendence on cte.fdate = tbl_Attendence.Datess 
where 
    tbl_Attendence.Datess is null

问题是SELECTCTE 内的第一个是VARCHAR(255)类型,而它的联合对应物(SELECTCTE 内的第二个)是一个DATE类型。由于您将这些结果相加,因此数据类型必须匹配。

有一个WHERE( fdate < '" + tday+"') 比较字符串值。在我看来,您希望这是动态 SQL。如果不先构建字符串,它将无法在纯 SQL 上工作。

我无法提出解决方案,因为我不知道您要完成什么。


如果 Damien 的建议是正确的,您可以使用以下方法找出缺少的日期数量tbl_Attendence

DECLARE @MinDate DATE = '2018-01-01'

DECLARE @MaxDate DATE = GETDATE()

;WITH cte AS 
(
    SELECT 
        @MinDate as fdate 

    UNION ALL 

    SELECT 
        DATEADD(day, 1, fdate) as fdate
    FROM 
        cte 
    WHERE 
        fdate < @MaxDate
)
SELECT 
    COUNT(fdate) AS Fdate 
FROM 
    cte 
where 
    NOT EXISTS (SELECT 'not in tbl_Attendence' FROM tbl_Attendence AS T WHERE T.Datess = cte.fdate)
OPTION
    (MAXRECURSION 0)

推荐阅读