【问题标题】:Subquery - Incorrect Syntax near the keyword 'declare'子查询 - 关键字“declare”附近的语法不正确
【发布时间】:2020-10-25 21:46:33
【问题描述】:

调试时遇到问题,希望有人能帮我解决这个问题。这是更长查询的一部分,但子查询“B”是唯一导致问题的部分,不知道为什么......我显然遗漏了一些东西。我正在使用 sql-server。

子查询本身运行良好,只是不能与查询的其余部分一起运行。

DECLARE @dstrt AS DATETIME
SET @dstrt = '2020-09-01 00:00:00'

DECLARE @dend AS DATETIME
SET @dend = '2020-09-30 23:59:59'


    DECLARE @UnpaidChgsTot table 
    (
    SiteID INT,
    Period nvarchar(30),
    dcDlqntTot money,
    iDelUnits int,
    dcPctUnits money,
    dcPctGrossPot money,
    dcPctActOcc money,
    iDatePeriod int
    )

    DECLARE @sLanguageTermColName nvarchar(20)
    SET @sLanguageTermColName = 'English'

    -- DECLARE some period counters
    DECLARE @StartDayNumber int
    DECLARE @EndDayNumber int
    SET @StartDayNumber = 0
    SET @EndDayNumber = -1

    --Hold the original date value
    DECLARE @dEndORig datetime
    SET @dEndORig = @dEnd

    DECLARE @dcGrossPotDenom money
    DECLARE @dcActOccDenom money
    DECLARE @iTotUnitsDenom int

    SET @dcGrossPotDenom =  1 
    SET @dcActOccDenom = 1
    SET @iTotUnitsDenom = 1
    --Define a holding table for charge balances by ChargeID
    DECLARE @BalT table
    (
        SiteID int,
        ChargeID int,
        LedgerID int,
        ChargeDescID int,
        sChgCategory nvarchar(20),
        sDefAcctCode nvarchar(20),
        dChgStrt datetime,
        dcBalAmt money,
        dcBalTax1 money,
        dcBalTax2 money
    )

    /*
     *  Updated.  Delete was taking too long to run, added to WHERE to get rid
     *  Date: 10192009
     *  Josh
     */
     --Fill the @BalT with charge balances for charges <=dEND
    INSERT INTO @BalT
    SELECT
        B.SiteID,
        B.ChargeID,
        B.LedgerID,
        B.ChargeDescID,
        CD.sChgCategory,
        CA.sDefAcctCode,
        B.dChgStrt,
        dcAmt,
        dcTax1,
        dcTax2
    FROM           -- PROBLEM STARTS HERE
    (
      DECLARE @ChargesT2 table
      (
        SiteID int,
        ChargeID int,
        ChargeDescID int,
        sChgCategory nvarchar(50),
        sDefAcctCode nvarchar(5),
        dChgStrt datetime,
        LedgerID int,
        dcAmt money,
        dcTax1 money,
        dcTax2 money,
        sChargeTag nvarchar(20)
      )
        
        DECLARE @fnPmtSumByChargeT Table 
        (
            SiteID INT,
            ChargeID int,
            dcPmtSum money
        )
    
        DECLARE @fnPmtSumByChargeT2 Table 
        (
            SiteID INT,
            ChargeID int,
            dcPmtSum money
        )
    
        DECLARE @ChargesTempT table
        (
            SiteID INT,
            ChargeID int,
            dcAmt money,
            dcTax1 money,
            dcTax2 money
        )

        Declare @ChargesT table
        (
        SiteID INT,
        ChargeID int,
        ChargeDescID int,
        sChgCategory nvarchar(50),
        sDefAcctCode nvarchar(5),
        dChgStrt datetime,
        LedgerID int,
        dcAmt money,
        dcTax1 money,
        dcTax2 money,
        sChargeTag nvarchar(20)
        )
    
        INSERT INTO @ChargesT2
        SELECT  
            C.SiteID,
            C.ChargeID, 
            C.ChargeDescID, 
            sChgCategory,
            sDefAcctCode,
            C.dChgStrt, 
            C.LedgerID,
            Coalesce(C.dcAmt,0.0) AS dcBalAmt,
            Coalesce(C.dcTax1,0.0) AS dcBalTax1, 
            Coalesce(C.dcTax2,0.0) AS dcBalTax2,
            CASE 
                WHEN CAST(CA.sDefAcctCode AS INT) = 4000 THEN N'Rent'
                WHEN CAST(CA.sDefAcctCode AS INT) = 4042 THEN N'LateFee'
                WHEN CAST(CA.sDefAcctCode AS INT) = 4041 THEN N'AdminFee'
                WHEN CAST(CA.sDefAcctCode AS INT) = 4070 THEN N'Insurance'
                WHEN CAST(CA.sDefAcctCode AS INT) BETWEEN 4060 AND 4068 OR CAST(CA.sDefAcctCode AS INT) BETWEEN 4071 AND 4079 THEN N'POS'
                --WHEN CAST(CA.sDefAcctCode AS INT) = 2020 THEN 'SecDep'
                ELSE N'Others'
            END as sChargeTag
        FROM Charges AS C
        INNER JOIN ChargeDesc AS CD ON C.ChargeDescID = CD.ChargeDescID
        LEFT OUTER JOIN ChartOfAccts AS CA ON CD.ChartofAcctID = CA.ChartOfAcctID
        WHERE 
             C.dDeleted IS NULL
            AND C.dChgStrt <= @dend
        --2016-01-12 - Case # 237424 - C158, L005, Unit 10478, Tenant - Zach Reese.
        --Commented out dCreated evaluation. This is because A/R does not prevent backdating charges from changing historical reports. There is no way these two reports 
        --can tie out in the same period if we do not allow backdating charges that we created in a future period. Ex. Late fee created on January 2, 2016, but dChgStrt of 12/29/2015.
        --AND dCreated <= @dEnd --This is to catch a case where NSF charges were added (backdated) after the report end date, affecting historical reporting. 02102011 Josh
            AND (bNSF = 0 OR (bNSF = 1 AND dCreated <= @dend))--updated the logic to be different for NSF charges to not change reports historically; this loigc is consistant with A/R. Case # 269909
        GROUP BY C.siteID, C.ChargeID, C.ChargeDescID, sChgCategory, sDefAcctCode, C.dChgStrt, C.LedgerID, C.dcAmt, C.dcTax1, C.dcTax2, CA.sDefAcctCode

        INSERT INTO @fnPmtSumByChargeT2
        SELECT 
            SiteID, 
            ChargeID, 
            dcPmtSum 
        FROM 
            (
            SELECT
            pay.SiteID,
            Pay.ChargeID, 
            SUM(pay.dcPmtAmt) AS dcPmtSum
            FROM 
                ( 
                SELECT 
                    SiteID, 
                    ChargeID, 
                    dcPmtAmt 
                FROM Payments 
                WHERE 
                    (dDeleted Is Null)
                    --AND (bNSF = 0) --this fn must return ALL payments to calculate balances correctly
                    AND (dPmt <= @dend)
                ) AS Pay
            GROUP BY SiteID, ChargeID
            ) AS P

        INSERT INTO @fnPmtSumByChargeT2
        SELECT
            C.SiteID,
            C.ChargeID,
            0
        FROM @ChargesT2 C

        INSERT INTO @fnPmtSumByChargeT
        SELECT
            P.SiteID,
            P.ChargeID,
            SUM(P.dcPmtSum)
        FROM @fnPmtSumByChargeT2 P
        GROUP BY P.SiteID, P.ChargeID

        INSERT INTO @ChargesTempT
        SELECT
            P.SiteID,
            P.ChargeID,
            C.dcAmt - Coalesce(dbo.fnPartNonTax(C.dcAmt, C.dcTax1, C.dcTax2, P.dcPmtSum, 2),0.0),
            C.dcTax1 - Coalesce(dbo.fnPartTax1(C.dcAmt, C.dcTax1, C.dcTax2, P.dcPmtSum, 2,2),0.0), 
            C.dcTax2 - Coalesce(dbo.fnPartTax2(C.dcAmt, C.dcTax1, C.dcTax2, P.dcPmtSum,2,2),0.0)
        FROM @ChargesT2 C
        INNER JOIN @fnPmtSumByChargeT P ON C.ChargeID = P.ChargeID
        GROUP BY P.SiteId, P.ChargeID, C.dcAmt, dcTax1, dcTax2, dcPmtSum
        HAVING (dcAmt + dcTax1 + dcTax2 - dcPmtSum) > 0  -- Removed 0 sum columns: This was a major bottleneck for this function  10202009 J

        INSERT INTO @ChargesT
        SELECT 
            C.SiteID,
            C.ChargeID,
            C.ChargeDescID,
            C.sChgCategory,
            C.sDefAcctCode,
            C.dChgStrt,
            C.LedgerID,
            CT.dcAmt,
            CT.dcTax1,
            CT.dcTax2,
            C.sChargeTag
        FROM @ChargesT2 C
        INNER JOIN @ChargesTempT CT ON C.ChargeID = CT.ChargeID 

    SELECT *
    FROM @ChargesT
    AS ChargeT      
    ) AS B                              -- PROBLEM ENDS HERE

    INNER JOIN ChargeDesc AS CD ON B.ChargeDescID = CD.ChargeDescID AND B.Siteid = CD.SiteID

如果有帮助,我会在注释中指出“问题从这里开始”和“问题从这里结束”。

提前致谢。

【问题讨论】:

  • 您不能在子查询中声明表变量。
  • 我有一种感觉,就是这样……有没有简单的解决方法?也许是临时表?
  • 无论你使用什么表类型,你都必须在从中选择之前声明它。就目前而言,您的查询无论如何都没有意义,您正试图在创建表的同时从表中进行选择...确保其中没有数据,那么重点是什么?
  • 在你声明它的那一刻,表中不能有数据......你INSERT INTO @ChargesT2SELECT 语句中尝试创建@ChargesT2 后有很多行。这根本没有意义。太没有意义了,以至于我实际上无法建议您可能要完成的工作...
  • 我通过将声明添加到整个查询的开头(子查询之外)来修复它。感谢您为我指明正确的方向。这绝对是一个奇怪的数据集,使用来自原始开发人员的查询语言,并且令人困惑/难以理解。所以我很难遵循逻辑。这也是一个快照,依赖于查询中未包含的多层预先存在的逻辑。

标签: sql sql-server subquery declare


【解决方案1】:

在子查询中,您唯一要做的就是编写一个选择语句。你不能写任何你想要的东西,就像它是一个代码块。

在您的情况下,您可以通过将所有这些表变量移到括号外并填充它们来完成您想要的操作,然后在括号内进行选择。就像我说的,它不是代码块,没有局部变量。没有比这更漂亮的方式了。 SQL 是一种用于查询信息的简单语言。就是这样。

或者,您可能希望使用公用表表达式 (CTEs) 为每个子查询命名。子查询不作为任何临时变量或表存在,就像在主查询期间可用的助手名称一样。这可能会解决您想要做的事情。

【讨论】:

    猜你喜欢
    • 2016-06-08
    • 2013-12-04
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 2012-01-12
    • 1970-01-01
    • 2018-06-16
    相关资源
    最近更新 更多