Sql server 如何将序列号连接到无关数据(SQL Server)
这个问题是我之前的一个问题的后续问题,这个问题是关于在不使用游标的情况下发现未使用的序列号范围。我正在使用SQLServer2005 我需要对这些数字做的是将这些数字分配给表中的记录。我只是想不出一种方法来将数字表与需要这些数字的记录联系起来 想到的一个可能的解决方案是使用标识将记录插入临时表中,并使用数字范围的开头作为标识种子。这种方法唯一的问题是,如果数字序列中存在间隙,那么我最终会得到重复的控制数字 这就是我的表格过于简化的样子: 数字表:Sql server 如何将序列号连接到无关数据(SQL Server),sql-server,sql-server-2005,tsql,sequential-number,Sql Server,Sql Server 2005,Tsql,Sequential Number,这个问题是我之前的一个问题的后续问题,这个问题是关于在不使用游标的情况下发现未使用的序列号范围。我正在使用SQLServer2005 我需要对这些数字做的是将这些数字分配给表中的记录。我只是想不出一种方法来将数字表与需要这些数字的记录联系起来 想到的一个可能的解决方案是使用标识将记录插入临时表中,并使用数字范围的开头作为标识种子。这种方法唯一的问题是,如果数字序列中存在间隙,那么我最终会得到重复的控制数字 这就是我的表格过于简化的样子: 数字表: Number ------- 102
Number
-------
102314
102315
102319
102320
102324
102329
数据表:
CustomerId PaymentAmt ControlNumber
---------- ---------- -------------
1001 4502.01 NULL
1002 890.00 NULL
9830 902923.34 NULL
我需要一种方法来实现它,因此我最终会:
CustomerId PaymentAmt ControlNumber
---------- ---------- -------------
1001 4502.01 102314
1002 890.00 102315
9830 902923.34 102319
不必使用游标就可以实现这一点吗?我之所以避免使用游标,是因为我们当前的实现使用游标,而且由于它在12000条记录上慢了8分钟,所以我一直在寻找替代方法
注意:感谢所有发布答案的人。所有这些都很好,我必须选择一个似乎更容易实现和维护的,无论是谁在我之后。非常感谢。您需要一些东西将两个表连接在一起。可以在两个表之间匹配的某些数据值 我假设你的数字表中不仅仅有一列数字。如果其中有任何内容可以与您的数据表相匹配,那么您可以进行更新 如何使用游标更新数据表?尝试以下操作:
;WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY CustomerId) Corr
FROM DataTable
)
UPDATE CTE
SET CTE.ControlNumber = B.Number
FROM CTE
JOIN ( SELECT Number, ROW_NUMBER() OVER(ORDER BY Number) Corr
FROM NumberTable) B
ON CTE.Corr = B.Corr
编辑添加代码,通过更新和删除的输出caluse从@Number中删除已用值
尝试使用ROW_NUMBER加入它们:
DECLARE @Number table (Value int)
INSERT @Number VALUES (102314)
INSERT @Number VALUES (102315)
INSERT @Number VALUES (102319)
INSERT @Number VALUES (102320)
INSERT @Number VALUES (102324)
INSERT @Number VALUES (102329)
DECLARE @Data table (CustomerId int, PaymentAmt numeric(10,2),ControlNumber int)
INSERT @Data VALUES (1001, 4502.01 ,NULL)
INSERT @Data VALUES (1002, 890.00 ,NULL)
INSERT @Data VALUES (9830, 902923.34 ,NULL)
DECLARE @Used table (Value int)
;WITH RowNumber AS
(
SELECT Value,ROW_NUMBER() OVER(ORDER BY Value) AS RowNumber FROM @Number
)
,RowData AS
(
SELECT CustomerId,ROW_NUMBER() OVER(ORDER BY CustomerId) AS RowNumber, ControlNumber FROM @Data WHERE ControlNumber IS NULL
)
UPDATE d
SET ControlNumber=r.Value
OUTPUT r.Value INTO @Used
FROM RowData d
INNER JOIN RowNumber r ON d.RowNumber=r.RowNumber
DELETE @Number WHERE Value IN (SELECT Value FROM @Used)
SELECT * FROM @Data
SELECT * FROM @Number
输出:
CustomerId PaymentAmt ControlNumber
----------- --------------------------------------- -------------
1001 4502.01 102314
1002 890.00 102315
9830 902923.34 102319
(3 row(s) affected)
Value
-----------
102320
102324
102329
(3 row(s) affected)
基于链接问题中的Martin代码,您可以为没有控制编号的所有行指定一个行号。然后给所有未使用的数字一个行号。将这两个集合连接在一起,每行将得到一个唯一的编号:
DECLARE @StartRange int, @EndRange int
SET @StartRange = 790123401
SET @EndRange = 790123450;
; WITH YourTable(ControlNumber, CustomerId) AS
(
SELECT 790123401, 1000
UNION ALL SELECT 790123402, 1001
UNION ALL SELECT 790123403, 1002
UNION ALL SELECT 790123406, 1003
UNION ALL SELECT NULL, 1004
UNION ALL SELECT NULL, 1005
UNION ALL SELECT NULL, 1006
)
, YourTableNumbered(rn, ControlNumber, CustomerId) AS
(
select row_number() over (
partition by IsNull(ControlNumber, -1)
order by ControlNumber)
, *
from YourTable
)
, Nums(N) AS
(
SELECT @StartRange
UNION ALL
SELECT N+1
FROM Nums
WHERE N < @EndRange
)
, UnusedNums(rn, N) as
(
select row_number() over (order by Nums.N)
, Nums.N
from Nums
where not exists
(
select *
from YourTable yt
where yt.ControlNumber = Nums.N
)
)
select ytn.CustomerId
, IsNull(ytn.ControlNumber, un.N)
from YourTableNumbered ytn
left join
UnusedNums un
on un.rn = ytn.rn
OPTION (MAXRECURSION 0)
您所需要的只是数据表中的确定顺序。如果有,可以使用行号作为联接条件:
with cte as (
select row_number() over (order by CustomerId) as [row_number],
ControlNumber
from [Data Table]
where ControlNumber is null),
nte as (
select row_number() over (order by Number) as [row_number],
Number
from [Numbers])
update cte
set ControlNumber = Number
from cte
join nte on nte.[row_number] = cte.[row_number];
如果您需要它是并发性证明,它确实会变得更复杂。嵌套游标。每个客户对应一个光标,每个号码对应一个光标。如果该数字正在使用,我将递增并重新检查,直到找到一个未使用的数字。然后我去找下一位顾客,重新检查每个号码,直到找到合适的号码,等等。这就是为什么它这么慢的原因。我来这里就是为了准确地回答这个问题!从这个问题来看,我认为有些行已经有了一个ControlNumber。问题是为每一行分配一个未使用的编号,而不使用ControlNumber。您的答案为每行分配一个新的数字。跳过填充的控制数字很简单,只需在cte内添加一个WHERE caluse。这将与第一个cte不匹配,留下一些未使用的数字。但是nvmd,似乎OP在这一点之前过滤掉了未使用的数字@安多马尔:为什么它会让数字闲置?@安多马尔:是的,可能吧。我实际上没有读到前面的问题,我认为这是一次更新+我同意你的回答。天哪!这将尽可能长的结果集14000条记录从8分钟减少到3秒。三秒钟。先生,我欠你一杯啤酒。至于正在使用的数字,@Andomar,我已经在之前的查询中删除了这些数字。@enriquein:谢谢你的啤酒,现在我有理由有时间去波多黎各-