在 SQL 查询中使用声明的变量时出错

Error when using a declared variable in SQL Query

我每 cnsmr_accnt_id 付款几个月。我希望查看过去 4 个月每月的总付款额。像这样:

Cnsmr_accnt_id   |   Wrkgrp_nm    |  Apr15_Tot  |  May15_Tot  |  Jun15_Tot  |  Jul15_Tot
12345            |Workgrp1        |  123424     |  1243255    |  232342     |  23232323
12347            |Workgrp4        |  123323     |  1244455    |  324342     |  232323

我正在尝试使用 Pivot 来执行此操作,但在使用以下代码时一直出现错误。我怀疑这与变量@Dates 范围有关。

@Dates 给我的值是 Apr15、May15、Jun15、Jul15,这是正确的。

如果我将其直接替换为 Select 代替 @Dates,则查询有效。但是当我使用@Dates 时,它会出错。 (“@Dates”附近的语法不正确。)

我也试过将用于设置@Dates 的整个"formula" 放入select 语句中,但这也会出错。 (关键字 'left' 附近的语法不正确)

Declare @Dates as nvarchar(max); 
--Builds up a string of dates for the last 4 months. 
Set @Dates = left(datename(Month, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 2) + ',' +
 left(datename(Month, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 2)+ ',' +
 left(datename(Month, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 2)+ ',' +
 left(datename(Month, getdate()), 3) + 
 right(datename(year, getdate()), 2);

 --Print @dates
--Example output = Apr15,May15,Jun15,Jul15

--Use a pivot to get the totals per cnsmr_accnt_id for the last 4 months. 
Select *
 from
(
Select  
    capj.cnsmr_accnt_id,
    wrkgrp_nm,
    max(UDEFINST_AMT) as Instlmnt,
    sum(cnsmr_accnt_pymnt_amnt) as Mnth_Tot, 
--Gives the Month & year (Eg Jul15)
    left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2) as Month_Yr
from 
    dbo.cnsmr_accnt_pymnt_jrnl capj  
        inner join 
    UDEFGENERAL UG 
        on 
        capj.cnsmr_accnt_id = UG.cnsmr_accnt_id
        Inner join
    wrkgrp w 
        on
        capj.wrkgrp_id = w.wrkgrp_id
where
cnsmr_accnt_pymnt_stts_cd in (5)
and cnsmr_accnt_pymnt_pstd_dt between
--Go back to the 1st day 4 months back
datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)
and 
getdate()
group by capj.cnsmr_accnt_id, 
left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2), 
 wrkgrp_nm) as Mnth_Tot_Tbl
 pivot 
 (
 sum(Mnth_Tot) 
 for 
 Month_Yr in (@Dates)) as Piv

您需要使用动态 sql 或使用以下内容代替 (@Dates)

中的 Month_Yr
','+@Dates+',' like '%,'+Month_Yr+',%' 

如果您想要过去 4 个月的数据,我建议您采用不同的方法,而不是按月和年分组,而是按自本月以来的月数分组。因此,与其尝试动态旋转,不如旋转静态数字 (0, 1, 2, 3);

SELECT  *
FROM    (   SELECT  capj.cnsmr_accnt_id,
                    wrkgrp_nm,
                    Instlmnt = MAX(udefinst_amt),
                    Mnth_Tot = SUM(cnsmr_accnt_pymnt_amnt), 
                    MonthsSinceToday = DATEDIFF(MONTH, cnsmr_accnt_pymnt_pstd_dt, GETDATE())
            FROM    dbo.cnsmr_accnt_pymnt_jrnl AS capj  
                    INNER JOIN Udefgeneral AS ug
                        ON capj.cnsmr_accnt_id = ug.cnsmr_accnt_id
                    INNER JOIN wrkgrp AS w 
                        ON capj.wrkgrp_id = w.wrkgrp_id
            WHERE   cnsmr_accnt_pymnt_stts_cd IN (5)
            AND     cnsmr_accnt_pymnt_pstd_dt >= DATEADD(MONTH, DATEDIFF(MONTH, '19000401', GETDATE()), '19000101')
            AND     cnsmr_accnt_pymnt_pstd_dt < GETDATE()
            GROUP BY cnsmr_accnt_id, wrkgrp_nm, DATEDIFF(MONTH, cnsmr_accnt_pymnt_pstd_dt, GETDATE())
        ) AS d
        PIVOT 
        (   SUM(Mnth_Tot)
            FOR MonthsSinceToday IN ([0], [1], [2], [3])
        ) AS pvt;

这种方法的缺点是您的日期不会是列 headers,但优点是您不需要使用动态 sql,并且列名应该很容易无论如何都由您的表示层处理。

 First Convert second part into dynamic string  and create string query after execute your Query
EXEC('Select *
 from
(
Select  
    capj.cnsmr_accnt_id,
    wrkgrp_nm,
    max(UDEFINST_AMT) as Instlmnt,
    sum(cnsmr_accnt_pymnt_amnt) as Mnth_Tot, 
--Gives the Month & year (Eg Jul15)
    left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2) as Month_Yr
from 
    dbo.cnsmr_accnt_pymnt_jrnl capj  
        inner join 
    UDEFGENERAL UG 
        on 
        capj.cnsmr_accnt_id = UG.cnsmr_accnt_id
        Inner join
    wrkgrp w 
        on
        capj.wrkgrp_id = w.wrkgrp_id
where
cnsmr_accnt_pymnt_stts_cd in (5)
and cnsmr_accnt_pymnt_pstd_dt between
--Go back to the 1st day 4 months back
datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)
and 
getdate()
group by capj.cnsmr_accnt_id, 
left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2), 
 wrkgrp_nm) as Mnth_Tot_Tbl
 pivot 
 (
 sum(Mnth_Tot) 
 for 
 Month_Yr in (' + @Dates + ')) as Piv')

所以我们有 2 个以上的答案。感谢 GarethD 和 Pradip。

总而言之,我测试了 Pradip 的解决方案如下:

Declare @Dates as nvarchar(max); 
--Builds up a string of dates for the last 4 months. 
Set @Dates = left(datename(Month, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 2) + ',' +
 left(datename(Month, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 2)+ ',' +
 left(datename(Month, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 3) + 
 right(datename(year, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 2)+ ',' +
 left(datename(Month, getdate()), 3) + 
 right(datename(year, getdate()), 2);


EXEC('Select *
 from
(
Select  
    capj.cnsmr_accnt_id,
    wrkgrp_nm,
    max(UDEFINST_AMT) as Instlmnt,
    sum(cnsmr_accnt_pymnt_amnt) as Mnth_Tot, 
--Gives the Month & year (Eg Jul15)
    left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2) as Month_Yr
from 
    dbo.cnsmr_accnt_pymnt_jrnl capj  
        inner join 
    UDEFGENERAL UG 
        on 
        capj.cnsmr_accnt_id = UG.cnsmr_accnt_id
        Inner join
    wrkgrp w 
        on
        capj.wrkgrp_id = w.wrkgrp_id
where
cnsmr_accnt_pymnt_stts_cd in (5)
and cnsmr_accnt_pymnt_pstd_dt between
--Go back to the 1st day 4 months back
datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)
and 
getdate()
group by capj.cnsmr_accnt_id, 
left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2), 
 wrkgrp_nm) as Mnth_Tot_Tbl
 pivot 
 (
 sum(Mnth_Tot) 
 for 
 Month_Yr in (' + @Dates + ')) as Piv')