SQL Server 根据 case 的结果将计数器加 1 时

Posted

技术标签:

【中文标题】SQL Server 根据 case 的结果将计数器加 1 时【英文标题】:SQL Server add 1 to counter based on result of case when 【发布时间】:2018-02-01 21:48:48 【问题描述】:

谁能告诉我我添加的代码是否可以工作? 它给了我语法错误,我不知道为什么。

问题 票号是连续的,但偶尔会有几百万个数字的大突破。服务器无法将所有几百万行计算为丢失,因此我想在代码进入下一个游标之前设置一个 50 个丢失的限制。

样本数据集

添加了更多代码以提供问题的上下文。

DECLARE DB_CURSOR CURSOR FOR 

SELECT PCC
FROM 
#PCC_TEMP


OPEN DB_CURSOR
FETCH NEXT FROM DB_CURSOR INTO
@NAME

WHILE @@FETCH_STATUS = 0

BEGIN

;WITH Missing (missnum, maxid)
AS
(
 SELECT (select min(Ticket_no) from #Temp where PCC = @name) AS missnum, (select max(Ticket_no) from #Temp where PCC = @name)
 UNION ALL
 SELECT missnum + 1, maxid FROM Missing
 WHERE missnum < maxid

)

SELECT missnum as [Ticket],
case when(tt.Ticket_no is NULL) then '' else tt.routing_info END as [Routing],
case when(tt.Ticket_no is NULL) then '' else tt.trip END as [Trip],
case when(tt.Ticket_no is NULL) then '' else tt.PNR END as [PNR],
case when(tt.Ticket_no is NULL) then '' else tt.PCC END as [PCC],
case when(tt.Ticket_no is NULL) then 'Missing' else 'Present' END as [Status],
case when(tt.Ticket_no is NULL) then     SET @Missing_Counter = @Missing_Counter +1 END

FROM Missing
LEFT OUTER JOIN #Temp tt on tt.Ticket_no = Missing.missnum
OPTION (MAXRECURSION 0); 


FETCH NEXT FROM DB_CURSOR INTO
@NAME

END

CLOSE DB_CURSOR

DEALLOCATE DB_CURSOR

DROP TABLE #Temp

DROP TABLE #PCC_TEMP

干杯

戴夫

【问题讨论】:

你能提供更多你的 SQL 吗? 添加了更多代码,谢谢 你的问题是你试图在你的选择中设置。 看起来这是递归 cte 中的最终选择,你能发布整个 cte 吗?另外,丢失计数器的最终目标是什么(您需要运行总数还是总数)? 感谢您的更新。我认为最能帮助人们的是添加一些示例模式/数据和所需的结果。我相信您只需要 recursive-cte (首选,作为基于集合的方法)或游标,而不是两者。您还可以用您使用的 SQL Server 版本(08/12/14/16/等)标记问题吗? 【参考方案1】:

在 2008 年以后的 SQL Server 中,您可以只使用 lag()lead()。你可以这样做:

select (ticket_number + 1) as first_missing,
       (next_ticket_number - 1) as last_missing,
       (next_ticket_number - ticket_number - 1) as num_missing
from (select t.*, lead(ticket_number) over (order by ticket_number) as next_ticket_number
      from #Temp t
     ) t
where next_ticket_number <> ticket_number + 1;

忘记你的语法错误。无论如何,代码可能真的效率低下。另外,我不明白您为什么要为此使用光标。尽可能使用基于集合的方法。

在早期版本中,您可以这样做:

select (ticket_number + 1) as first_missing,
       (next_ticket_number - 1) as last_missing,
       (next_ticket_number - ticket_number - 1) as num_missing
from (select t.*, t2.ticket_number as next_ticket_number
      from #Temp t cross apply
           (select top (1) t2.ticket_number
            from #temp t2
            where t2.ticket_number > t.ticket_number
            order by t2.ticket_number asc
           ) t2
     ) t
where next_ticket_number <> ticket_number + 1;

虽然这比lead() 效率低,但它可以利用ticket_number() 上的索引。

【讨论】:

我正在使用 2008 R2,但遗憾的是,我不确定 Lag 和 Lead 是否适合我。【参考方案2】:

你真正想要的是计算空票号,那么为什么不计算空票号呢?

SELECT @Missing_Counter = COUNT(1) 
FROM Table
WHERE Ticket_no is NULL

【讨论】:

我可以连续有 300 万个空值,但过程太繁重了。我想设置 50 个空值的限制,然后跳到下一步。

以上是关于SQL Server 根据 case 的结果将计数器加 1 时的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql server中使用if语句和case

SQL Server 2012:如何在 @Var 前后使用文字在 Case 语句中显示 @Var 结果

如何推断 SQL Server 中的日期以计算每日计数?

SQL Server:使用case插入两个表

SQL Server:CASE 语句中的 OR 语句

如何把SQL server 表里插入转换科学计数法的方法。