Vì dữ liệu của bạn trông hơi giống phân cấp. Tôi nghĩ về việc sử dụng nó. Các phiên bản ban đầu không có quy mô lên tới 1 triệu hàng, tuy nhiên một vài lựa chọn lập chỉ mục trên bảng tạm thời chính đã giúp ích. Tuy nhiên, các vấn đề cũng có thể là do dữ liệu thử nghiệm của tôi, vì vậy bạn có thể cho tôi biết thêm một chút về hệ thống phân cấp của bạn không? Ví dụ, có bao nhiêu cha mẹ cấp cao nhất, trung bình có bao nhiêu cấp độ, mỗi cấp độ có bao nhiêu con?
Trong khi đó, đây là một phiên bản để bạn có thể xem qua nó và xem liệu hierarchyId
có thể làm việc cho bạn không.
Ý tưởng cơ bản là tạo một bảng tạm thời với các id gốc được chuyển đổi thành hierarchyIds
, sau đó đi theo cấu trúc phân cấp để tìm ra dòng dõi. Bảng tạm thời này (có thể là vĩnh viễn) sau đó có thể được sử dụng để di chuyển:
USE tempdb
GO
SET NOCOUNT ON
GO
IF OBJECT_ID('[dbo].[Almoxarifado]') IS NOT NULL DROP TABLE [dbo].[Almoxarifado]
IF OBJECT_ID('[dbo].[Almoxarifado2]') IS NOT NULL DROP TABLE [dbo].[Almoxarifado2]
GO
CREATE TABLE [dbo].[Almoxarifado](
[idAlmoxarifado] [varchar](20) NOT NULL,
[tipoAlmoxarifadoId] [varchar](30) NOT NULL,
[entidadeId] [bigint] NOT NULL,
[dtInclusao] [smalldatetime] NOT NULL,
[dtUltimaAlteracao] [smalldatetime] NULL,
[descricao] [varchar](255) NOT NULL,
[terceiro] [bit] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Almoxarifado2](
[idMaster] [bigint] IDENTITY(1,1) NOT NULL,
[idAlmoxarifado] [int] NOT NULL,
[idAlmoxPai] [int] NOT NULL DEFAULT ((0)),
[entidadeId] [bigint] NOT NULL,
[tipoAlmoxarifadoId] [varchar](30) NOT NULL ,
[dtInclusao] [datetime] NULL DEFAULT (getdate()),
[dtUltimaAlteracao] [datetime] NULL,
[descricao] [varchar](255) NOT NULL,
[terceiro] [bit] NULL DEFAULT ((0)),
PRIMARY KEY ([idMaster])
)
GO
/*
-- Test data
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
VALUES
( '1', 'TESTE', 12, '29 Apr 2016', NULL, '0000000', 0 ),
( '1.1', 'TESTE', 12, '29 Apr 2016', NULL, '0000001', 0 ),
( '1.1.01', 'TESTE', 12, '29 Apr 2016', NULL, '0000002', 0 ),
( '1.1.01.01', 'TESTE', 12, '29 Apr 2016', NULL, '0000003', 0 ),
( '1.1.01.01.001', 'TESTE', 12, '29 Apr 2016', NULL, '0000004', 0 ),
( '1.1.01.01.002', 'TESTE', 12, '29 Apr 2016', NULL, '0000005', 0 ),
( '1.1.01.01.003', 'TESTE', 12, '29 Apr 2016', NULL, '0000006', 0 ),
( '1.1.01.01.004', 'TESTE', 12, '29 Apr 2016', NULL, '0000007', 0 ),
( '1.1.01.01.005', 'TESTE', 12, '29 Apr 2016', NULL, '0000008', 0 ),
( '1.1.01.01.006', 'TESTE', 12, '29 Apr 2016', NULL, '0000009', 0 )
GO
*/
-- Add 10 parent levels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
VALUES
( '1', 'TESTE', 1, '1 Jan 2016', NULL, '00000001', 0 ),
( '2', 'TESTE', 1, '1 Feb 2016', NULL, '00000002', 0 ),
( '3', 'TESTE', 1, '1 Mar 2016', NULL, '00000003', 0 ),
( '4', 'TESTE', 1, '1 Apr 2016', NULL, '00000004', 0 ),
( '5', 'TESTE', 1, '1 May 2016', NULL, '00000005', 0 ),
( '6', 'TESTE', 1, '1 Jun 2016', NULL, '00000006', 0 ),
( '7', 'TESTE', 1, '1 Jul 2016', NULL, '00000007', 0 ),
( '8', 'TESTE', 1, '1 Aug 2016', NULL, '00000008', 0 ),
( '9', 'TESTE', 1, '1 Sep 2016', NULL, '00000008', 0 ),
( '10', 'TESTE', 1, '1 Oct 2016', NULL, '00000010', 0 )
-- For each parent, add 3 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 5 idAlmoxarifado y FROM [dbo].[Almoxarifado] ) x
-- add n sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 8 idAlmoxarifado y FROM [dbo].[Almoxarifado] WHERE idAlmoxarifado Not Like '%.%' ) x
WHERE idAlmoxarifado Like '%.%'
-- Add 8 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 13 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%'
-- Add 9 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 21 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%.%'
GO
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 9 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%.%.%'
GO
-- Main hierarchyId processing
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL DROP TABLE #tmp
SELECT
IDENTITY( INT, 1, 1 ) AS idMaster,
idAlmoxarifado,
CAST( '/' + REPLACE( REPLACE( REPLACE( idAlmoxarifado, '.0', '.' ), '.0', '.' ), '.', '/' ) + '/' AS hierarchyid ) hId,
CAST( '/' + REPLACE( REPLACE( REPLACE( idAlmoxarifado, '.0', '.' ), '.0', '.' ), '.', '/' ) + '/' AS hierarchyid ).ToString() hString,
CAST( NULL AS INT ) AS idAlmoxarifado2,
CAST( NULL AS INT ) AS idAlmoxPai
INTO #tmp
FROM [dbo].[Almoxarifado]
GO
-- Index temp table to help with recursive CTE
ALTER TABLE #tmp ADD PRIMARY KEY ( idMaster )
ALTER TABLE #tmp ALTER COLUMN hId hierarchyId NOT NULL
CREATE UNIQUE INDEX _idx ON #tmp ( hId ) INCLUDE ( idAlmoxarifado, hString )
GO
-- Walk the hierarchy
;WITH cte AS (
SELECT 1 AS xlevel, idMaster, idAlmoxarifado, hId, hString, hId.GetLevel() getLevel, 0 AS parentId
FROM #tmp
WHERE hId.GetLevel() = 1
UNION ALL
SELECT xlevel + 1, t.idMaster, t.idAlmoxarifado, t.hId, t.hString, t.hId.GetLevel() getLevel, c.idMaster AS parentId
FROM cte c
INNER JOIN #tmp t ON c.hId = t.hId.GetAncestor(1)
)
UPDATE t
SET
-- Parse out the individual node, by taking its parent and stuffing it in front
t.idAlmoxarifado2 = CAST( REPLACE( STUFF( c.hString, 1, LEN(c.hId.GetAncestor(1).ToString()), '' ), '/', '' ) AS INT ),
t.idAlmoxPai = parentId
FROM cte c
INNER JOIN #tmp t ON c.idMaster = T.idMaster
-- Check results
SELECT *
FROM #tmp
Toàn bộ tập lệnh này (bao gồm tạo dữ liệu thử nghiệm) chỉ chạy trong vài phút trên máy tính xách tay của tôi.