顧客とその共同顧客がいるテーブルがあります。たとえば、顧客1には共同顧客2があります。顧客1は顧客3の共同顧客でもあります。
リンクされているすべての顧客をグループ化し、同じGroupCustNoを割り当てようとしています。以下の表1-2はリンクされており、3-1はリンクされています。したがって、2〜3もリンクされています。したがって、以下の表の1から8までのすべての顧客は相互にリンクされ、同じGroupCustNoを持ちます。
tbl_GroupCustomers:
CustNo JtCustNo GroupCustNo
--- ------- ------
1 2 null
2 null null
3 1 null
4 1 null
4 5 null
5 6 null
5 7 null
6 null null
7 null null
8 5 null
私が書いた再帰的なストアドプロシージャは以下のとおりです。私はこれを各CustNoのwhileループで呼び出しています:
exec usp_UpdateGroupCustomerNo 1、1ストアドプロシージャはほとんどの顧客で正常に実行されましたが、スローされました
一部のお客様では、再帰制限32がエラーに達しました。これらは、多くの共同顧客を持ち、他の顧客の共同顧客でもある顧客です。
ここでは再帰が機能しないようで、どのように進めるか途方に暮れています。この問題に対処する別の方法があるかどうか教えてください。
CREATE PROCEDURE [dbo].[usp_UpdateGroupCustomerNo]
@MainCustNo int, @GrpNo int
AS
declare @JtCustNo int; declare @MainCustNo2 int;
if exists(select 1 from tbl_GroupCustomer
where CustNo = @MainCustNo and groupcustomernumber is null)
begin
update tbl_GroupCustomer
set groupcustomernumber = @grpno
where CustNo = @MainCustNo
and groupcustomernumber is null
DECLARE db_cursor CURSOR LOCAL FOR
select JtCustNo
from tbl_GroupCustomer
where CustNo = @MainCustNo and JtCustNo is not null
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @JtCustNo
WHILE @@FETCH_STATUS = 0
BEGIN
select @JtCustNo as JtCustNo
exec usp_UpdateGroupCustomerNo @JtCustNo, @GrpNo
DECLARE db_cursor2 CURSOR LOCAL FOR
select CustNo
from tbl_GroupCustomer
where JtCustNo = @JtCustNo
and groupcustomernumber is null
OPEN db_cursor2
FETCH NEXT FROM db_cursor2 INTO @MainCustNo2
WHILE @@FETCH_STATUS = 0
BEGIN
if exists(select 1 from tbl_GroupCustomer
where CustNo = @MainCustNo2
and groupcustomernumber is null)
begin
exec usp_UpdateGroupCustomerNo @MainCustNo2, @GrpNo
end
FETCH NEXT FROM db_cursor INTO @MainCustNo2
END
CLOSE db_cursor2
DEALLOCATE db_cursor2
FETCH NEXT FROM db_cursor INTO @JtCustNo
END
CLOSE db_cursor
DEALLOCATE db_cursor
終わり
この回答は、プロシージャのどこかでOPTION (MAXRECURSION 0)
を使用して再帰制限を削除できないことを前提としています。
再帰的なソリューションを試すのにしばらく時間を費やしましたが、何を試しても、再帰の制限を下回ることを保証できませんでした。常に、より多くの反復を必要とするチェーンを構築できました。
だから、ここにテスト用の私のDDLと一緒に簡単なループソリューションがあります:
/*
IF OBJECT_ID('tempdb..#tbl_GroupCustomers') IS NOT NULL
DROP TABLE #tbl_GroupCustomers
CREATE TABLE #tbl_GroupCustomers
(CustNo int,
JtCustNo int,
GroupCustNo int)
INSERT #tbl_GroupCustomers
(CustNo, JtCustNo)
VALUES
(1,2),
(2,NULL),
(3,1),
(4,1),
(4,5),
(5,3),
(6,7),
(7,8),
(8,6),
(9,null)
SELECT *
FROM #tbl_GroupCustomers
*/
DECLARE @GN int = 1
DECLARE @seedCust int
DECLARE @count1 int, @count2 int
--Outer loop: iterate group numbers
WHILE EXISTS(SELECT * FROM #tbl_GroupCustomers WHERE GroupCustNo IS NULL)
BEGIN
--Find next ungrouped customer
SET @seedCust = (SELECT TOP 1 CustNo FROM #tbl_GroupCustomers WHERE GroupCustNo IS NULL)
--reset counts
SET @count1 = 0
SET @count2 = 1
--Start with a customer
--Give that customer a Group number
UPDATE GC
SET GroupCustNo = @GN
FROM #tbl_GroupCustomers GC
WHERE CustNo = @seedCust
--Inner loop
WHILE @count1 <> @count2
BEGIN
--How many records?
SELECT @count1 = COUNT(*) FROM #tbl_GroupCustomers WHERE GroupCustNo = @GN
--Give all linked records the same GN
UPDATE GC2
SET GC2.GroupCustNo = @GN
FROM (SELECT CustNo, JtCustNo
FROM #tbl_GroupCustomers
WHERE GroupCustNo = @GN
) GC1
INNER JOIN #tbl_GroupCustomers GC2
ON GC1.CustNo = GC2.JtCustNo
OR GC1.JtCustNo = GC2.CustNo
OR GC1.CustNo = GC2.CustNo
OR GC1.JtCustNo = GC2.JtCustNo
--How many records? If same, it ends loop
SELECT @count2 = COUNT(*) FROM #tbl_GroupCustomers WHERE GroupCustNo = @GN
END
SET @GN +=1
END
開始テーブル:
CustNo JtCustNo GroupCustNo
----------- ----------- -----------
1 2 NULL
2 NULL NULL
3 1 NULL
4 1 NULL
4 5 NULL
5 3 NULL
6 7 NULL
7 8 NULL
8 6 NULL
9 NULL NULL
結果:
CustNo JtCustNo GroupCustNo
----------- ----------- -----------
1 2 1
2 NULL 1
3 1 1
4 1 1
4 5 1
5 3 1
6 7 2
7 8 2
8 6 2
9 NULL 3