Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何将序列号连接到无关数据(SQL Server)_Sql Server_Sql Server 2005_Tsql_Sequential Number - Fatal编程技术网

Sql server 如何将序列号连接到无关数据(SQL Server)

Sql server 如何将序列号连接到无关数据(SQL Server),sql-server,sql-server-2005,tsql,sequential-number,Sql Server,Sql Server 2005,Tsql,Sequential Number,这个问题是我之前的一个问题的后续问题,这个问题是关于在不使用游标的情况下发现未使用的序列号范围。我正在使用SQLServer2005 我需要对这些数字做的是将这些数字分配给表中的记录。我只是想不出一种方法来将数字表与需要这些数字的记录联系起来 想到的一个可能的解决方案是使用标识将记录插入临时表中,并使用数字范围的开头作为标识种子。这种方法唯一的问题是,如果数字序列中存在间隙,那么我最终会得到重复的控制数字 这就是我的表格过于简化的样子: 数字表: Number ------- 102

这个问题是我之前的一个问题的后续问题,这个问题是关于在不使用游标的情况下发现未使用的序列号范围。我正在使用SQLServer2005

我需要对这些数字做的是将这些数字分配给表中的记录。我只是想不出一种方法来将数字表与需要这些数字的记录联系起来

想到的一个可能的解决方案是使用标识将记录插入临时表中,并使用数字范围的开头作为标识种子。这种方法唯一的问题是,如果数字序列中存在间隙,那么我最终会得到重复的控制数字

这就是我的表格过于简化的样子:

数字表:

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:谢谢你的啤酒,现在我有理由有时间去波多黎各-