【问题标题】:Incorrect Syntax near WithWith 附近的语法不正确
【发布时间】:2021-12-23 10:52:46
【问题描述】:

无论我将 With 语句放在 SQL 查询中的什么位置,下一行中的 keyword 总是显示错误,“keyword 附近的语法不正确”。我也试过放分号。

; WITH Commercial_subset AS
(
    SELECT DISTINCT
        PRDID_Clean, Value, [Year] 
    FROM
        Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial]  
    WHERE
        MEASURE = 'Unit Growth Rate'
)
--error appears at truncate
TRUNCATE TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]

示例 1:

[示例 1][1]

示例 2:

[示例 2][2]

我错过了什么? [1]:https://i.stack.imgur.com/lkfVd.png [2]:https://i.stack.imgur.com/tZRnG.png

在 cmets 中获得建议后我的最终代码,

    --Ensure the correct database is selected for creating the views
    USE Reporting_db_SPKPI
    
    --Create the table where new values will be appended
    Insert into Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]
    Select *, Replace(productID,'-','') as ProductID_clean from  Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR]
    GO
    
    --Create a subset as view which will be used for join later
    Create or Alter View QRY_Commerical_Subset AS
        Select Distinct PRDID_Clean, Value, [Year] From Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial]  where MEASURE = 'Unit Growth Rate'
    Go
    
    --Create a view with distinct list of all SKUs
    CREATE OR ALTER VIEW QRY_RCCP_TEMP AS 
        SELECT 
            PRODUCTID, ROW_NUMBER() Over (ORDER BY ProductID) AS ID 
        FROM (
            SELECT 
                DISTINCT A.ProductID_clean ProductID 
            FROM 
                Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup] A 
            LEFT JOIN 
                Reporting_db_SPKPI.DBO.QRY_Commerical_Subset B ON A.ProductID_clean = B.PRDID_Clean 
            WHERE 
                B.PRDID_Clean IS NOT NULL --and A.filename = 'Capacity Planning_INS_Springhill'  --DYNAMIC VARIABLE HERE
                and Cast(A.SnapshotDate as date) = 
                    (SELECT Max(Cast(SnapshotDate as date)) FROM reporting_db_spkpi.dbo.tbl_RCCP_3_NR)
        ) T
    GO
    
    SET NOCOUNT ON
    
    -- For every product id from the distinct list iterate the following the code
    DECLARE @I INT = 1
    WHILE @I <= (SELECT MAX(ID) FROM QRY_RCCP_TEMP)
    BEGIN
    
        DECLARE @PRODUCT NVARCHAR(50) = (SELECT PRODUCTID FROM QRY_RCCP_TEMP WHERE ID = @I)
        DROP TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
        
        --Retrieve last 12 months of value from NR and add it to a temp table in increasing order of their months. These 12 data points will be baseline
        SELECT 
            Top 12 A.*, 
            Case When B.[Value] is Null then 0 else CAST(B.[Value] as float) End GROWTH
        INTO 
            Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
        FROM 
            Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup] A
        LEFT JOIN 
            --using the view here
            QRY_Commerical_Subset B ON B.PRDID_Clean = A.ProductID_clean AND B.[YEAR] = YEAR(A.[MONTH])+1 
        WHERE 
            A.PRODUCTID= @PRODUCT
            AND Cast(A.SnapshotDate AS DATE) = (SELECT Max(Cast(SnapshotDate AS DATE)) FROM reporting_db_spkpi.dbo.[tbl_RCCP_3_NR_dup])
        Order by 
            [Month] desc
    
        -- Generate 3 years of data
        DECLARE @J INT = 1
        WHILE @J<=3
        BEGIN
            --Calculate next year's value
            UPDATE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
            SET 
                [Value] = [Value]*(1+ GROWTH), 
                [MONTH] = DATEADD(YEAR,1,[Month]),
                MonthCode= 'F' + CAST(CAST(SUBSTRING(MonthCode,2,LEN(MonthCode)) AS INT) + 12 AS NVARCHAR(10))
            
            --Add it to the NR table.
            Insert into Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]
                (ProductID, MonthCode, Value, Month, FileName, 
                LastModifiedDate, SnapshotDate, Quarter, IsError, ErrorDescription)
            Select 
                ProductID, MonthCode, Value, Month, FileName, 
                LastModifiedDate, SnapshotDate, Quarter, IsError, ErrorDescription
            from 
                Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
    
            --Update growth rate for next year
            UPDATE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp] 
            SET GROWTH = Case When B.[Value] is Null then 0 else CAST(B.[Value] as float) End 
            FROM Reporting_db_SPKPI.DBO.QRY_Commerical_Subset B 
            WHERE B.PRDID_Clean = ProductID_clean AND [YEAR] = YEAR([MONTH])+1
    
            SET @J=@J+1
        END
        SET @I=@I+1
    END
    DROP VIEW QRY_RCCP_TEMP
    DROP VIEW QRY_Commerical_Subset

【问题讨论】:

  • ; 是终结者,而不是开始者。用它来结束一个陈述,而不是开始一个
  • 您不使用公用表表达式。在你定义它之后,你需要使用它。在TRUNCATE 声明之前选择您想要SELECT * FROM Commercial_subset; 吗?
  • 首先你的with 有什么意义? truncatedrop 都会影响整个表格。
  • “我在运行超过 2000 次的 while 语句中使用它。” 听起来像 XY Problem。 SQL 是一种基于集合的语言;有非常几次WHILE是正确的解决方案。
  • 是的,是时候养成这个习惯了。 @GSerg。 :)

标签: sql sql-server


【解决方案1】:

WITHCommon Table Expression,又名 CTE。

CTE 就像子查询的模板。

例如同一个子查询的这个join:

SELECT *
FROM (
    select distinct bar 
    from table1
    where foo = 'baz'
) AS foo1
JOIN (
    select distinct bar 
    from table1
    where foo = 'baz'
) AS foo2
  ON foo1.bar > foo2.bar

可以写成

WITH CTE_FOO AS (
  select distinct bar 
  from table1 
  where foo = 'baz' 
) 
SELECT *
FROM CTE_FOO AS foo1
JOIN CTE_FOO AS foo2
  ON foo1.bar > foo2.bar

它应与SELECT 一起使用。
不能与 TRUNCATE TABLEDROP TABLE 一起使用。
(虽然它可以与 UPDATE 一起使用)

因此,将 TRUNCATE 视为单独的语句。

TRUNCATE TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup];

WITH Commercial_subset AS
(
    SELECT DISTINCT
        PRDID_Clean, Value, [Year] 
    FROM
        Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial]  
    WHERE
        MEASURE = 'Unit Growth Rate'
)
SELECT *
FROM Commercial_subset;

顺便说一句,许多人编写 CTE 时使用前导 ; 的原因是,如果前一个语句没有以 ; 结尾,则 WITH 子句会引发错误。这只是避免该错误的一个小技巧。

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 2018-08-14
    相关资源
    最近更新 更多