CASE或IF内部CTE声明

时间:2017-02-28 05:53:42

标签: sql-server tsql

我试图基于另一个使用CTE的分区来增加列,到目前为止我有以下内容:

DECLARE @start      INT
DECLARE @end        INT
DECLARE @current    INT
DECLARE @contNum    INT

SET     @start      = (SELECT MAX(ContractIssueID) - 20 FROM Contract)
SET     @end        = (SELECT MAX(ContractIssueID) FROM Contract)
SET     @current    = (SELECT MIN(ContractIssueID) FROM Contract)
SET     @contNum    = 0

WHILE @current <= @end
BEGIN
    WITH CTE AS
    (
        SELECT ContractIssueID, JobID, ROW_NUMBER() OVER (PARTITION BY JobID ORDER BY JOBID DESC) AS RN
        FROM Contract
    )
    SELECT * FROM CTE
    WHERE ContractIssueID = @current
    SET @current = @current + 1
    CASE WHEN RN = 1 THEN SET @contNum = @contNum + 1 END
END

我在case语句中收到错误,当我尝试使用IF时,它不会将RN识别为列。

我有什么想法可以解决这个问题吗?

----编辑------------------------------------------

跑步时出错:

Msg 156, Level 15, State 1, Line 24
Incorrect syntax near the keyword 'CASE'.
Msg 102, Level 15, State 1, Line 25
Incorrect syntax near 'END'.

-----编辑-----------------------------------------

目的: 我在这个表中有三列(ContractIssueNumber,JobID和ContractNumber)。 ContractNumber应该是一个静态值,其中JobID是相同的,而contractissuNumber是增量的,如下所示:

ContractIssueNumber -- JobID -- ContractNumber

1                       100     1
2                       100     1
3                       101     2
4                       102     3
5                       102     3

最初我只是将ContractNumber设置为jobID,但这似乎导致了问题,所以我试图根据JobId列的分区将它们设置为1,2,3等。

-----编辑-----------------------------------------

感谢所有帮助,最终和更优雅的解决方案在下面

WITH CTE AS
(
    SELECT ContractIssueID
        , JobID
        , ContractNumber
        , DENSE_RANK() OVER (ORDER BY JOBID ) AS RN
            FROM Contract
)
UPDATE CTE SET ContractNumber = RN

3 个答案:

答案 0 :(得分:1)

您的RN在套装声明中不可用。 RN仅在select中可用,因此您需要使用RN在select内增加@ContNum,然后设置@current

WITH CTE AS
    (
        SELECT ContractIssueID, JobID, ROW_NUMBER() OVER (PARTITION BY JobID ORDER BY JOBID DESC) AS RN
        FROM Contract
    )
    SELECT @contNum = @contNum + CASE WHEN RN = 1 THEN 1 END
    FROM CTE
    WHERE ContractIssueID = @current

    SET @current = @current + 1

我认为你也想要dense_rank而不是row_number:

    SELECT ContractIssueID
    , JobID
    , DENSE_RANK() OVER (ORDER BY JOBID DESC) AS RN
        FROM Contract
--        WHERE ContractIssueID = @current skip this when not using the loop

答案 1 :(得分:1)

检查一下,

DECLARE @start      INT
DECLARE @end        INT
DECLARE @current    INT
DECLARE @contNum    INT

SELECT  @start=(MAX(ContractIssueID) - 20),@current=MIN(ContractIssueID) FROM Contract
SET     @end        = @start+20
SET     @contNum    = 0

WHILE @current <= @end
BEGIN
    WITH CTE AS
    (
        SELECT ContractIssueID, JobID, ROW_NUMBER() OVER (PARTITION BY JobID ORDER BY JOBID DESC) AS RN
        FROM Contract
    )
    SELECT @contNum = @contNum + CASE WHEN RN = 1 THEN 1 END
    FROM CTE
    WHERE ContractIssueID = @current
    SET @current = @current + 1

END
BTW,@ contNum的目的尚不清楚。 首先是什么样的真实场景?你为什么要循环更新?这是主要问题。

答案 2 :(得分:0)

试试这个,

SET @contNum=CASE WHEN RN = 1 then  = @contNum + 1 END