我正面临这个问题,我不知道如何解决。
我将组织结构存储在2个表,组织和关系中;我的目标是构建(可以通过存储过程或类似的东西) DENORMALIZED 表,报告每个组织单位一行,通往顶部的路径树,有一个固定的深度。
我实际上可以使用游标和其他类似的东西来做到这一点,但我想知道是否有更快的方法(游标需要超过4分钟处理~4500个对象代码)
organizations
表有四个字段:
relations
表有四个字段:
结果表应包含以下字段:
现在,我可以使用以下SQL
获取所有记录DECLARE
@datRif dateTime = convert(datetime, '20151231', 103),
@codUo char(8) = '50043899',
@withMe char(1) = ' ',
@currentUo char(8) = '50043899'
DECLARE @path TABLE (
leaf char(8),
ancestor char(8),
desAncestor varchar(50),
deepLevel int
)
DECLARE cUOs cursor for
SELECT objCode
FROM organizations
WHERE
objType = 'O' AND
begDate <= @datRif AND
endDate >= @datRif
OPEN cUOs
FETCH NEXT FROM cUOs
INTO @currentUo
WHILE @@FETCH_STATUS = 0
BEGIN
with n (codUo, deepLev) AS
(SELECT r.objCode, 0
FROM relations r
WHERE r.objCode = @currentUo and
r.begDate <= @datRif and r.endDate >= @datRif
UNION ALL
SELECT nplus1.fatherCode, n.deepLev + 1
FROM relations nplus1, n
WHERE n.codUo = nplus1.objCode and
nplus1.begDate <= @datRif and nplus1.endDate >= @datRif
)
insert into @path
select @currentUo as leaf, n.codUo, o.longText, n.deepLev
from n left outer join organizations o on n.codUo = o.objCode
WHERE (o.begDate <= @datRif and o.endDate >= @datRif) or
o.begDate = null
order by n.deepLev DESC, o.longText
-- Get the next UO code.
FETCH NEXT FROM cUOs
INTO @currentUo;
END
CLOSE cUOs
DEALLOCATE cUOs
SELECT *
from @path
这段代码给了我以下数据集:
leaf ancestor desAncestor deepLevel
50000135 50032466 HOLDING 1
50000135 50000135 CEO 0
50023726 50032466 HOLDING 2
50023726 50000135 CEO 1
50023726 50023726 CEO_HR 0
50016541 50032466 HOLDING 3
50016541 50000135 CEO 2
50016541 50023726 CEO_HR 1
50016541 50016541 CEO_HR_ORG 0
50043899 50032466 HOLDING 4
50043899 50000135 CEO 3
50043899 50023726 CEO_HR 2
50043899 50016541 CEO_HR_ORG 1
50043899 50043899 CEO_HR_ORG_HRIS 0
我真正需要的是这样的事情:
object object descr root root desc uo1 uo1 desc uo2 uo2 desc uo3 uo3 desc uo4 uo4 desc
50043899 CEO_HR_ORG_HRIS 50032466 HOLDING 50000135 CEO 50023726 CEO_HR 50016541 CEO_HR_ORG
50016541 CEO_HR_ORG 50032466 HOLDING 50000135 CEO 50023726 CEO_HR
50023726 CEO_HR 50032466 HOLDING 50000135 CEO
50000135 CEO 50032466 HOLDING
如果有人想看一下,我会添加一些脚本来生成表格和数据。 (正在运行的DB是MS-SQL 2008 r2)
提前谢谢
保
/****** Object: Table [dbo].[organizations] Script Date: 08/01/2016 17:44:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[organizations](
[objCode] [nvarchar](8) NOT NULL,
[begDate] [datetime] NOT NULL,
[endDate] [datetime] NOT NULL,
[longText] [nvarchar](40) NULL,
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[relations] Script Date: 08/01/2016 17:46:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[relations](
[fatherCode] [nvarchar](8) NOT NULL,
[objCode] [nvarchar](8) NOT NULL,
[begDate] [datetime] NOT NULL,
[endDate] [datetime] NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50000135', CAST(0x00008C8700000000 AS DateTime), CAST(0x000095CE00000000 AS DateTime) N'CEO')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x000090F300000000 AS DateTime), CAST(0x0000919D00000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000919E00000000 AS DateTime), CAST(0x0000936F00000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000937000000000 AS DateTime), CAST(0x0000945600000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x0000943E00000000 AS DateTime), CAST(0x0000945200000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x0000945300000000 AS DateTime), CAST(0x0000945600000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000945700000000 AS DateTime), CAST(0x0000945700000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x0000945700000000 AS DateTime), CAST(0x0000946000000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000945800000000 AS DateTime), CAST(0x0000946000000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000946100000000 AS DateTime), CAST(0x0000974A00000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x0000946100000000 AS DateTime), CAST(0x000097B300000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50000135', CAST(0x000095CF00000000 AS DateTime), CAST(0x00009A1500000000 AS DateTime), N'CEO')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000974B00000000 AS DateTime), CAST(0x000097F000000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50032466', CAST(0x0000977700000000 AS DateTime), CAST(0x0000A0DC00000000 AS DateTime), N'HOLDING')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x000097B400000000 AS DateTime), CAST(0x000098A800000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x000097F100000000 AS DateTime), CAST(0x0000A14900000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50023726', CAST(0x000098A900000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime), N'CEO_HR')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50000135', CAST(0x00009A1600000000 AS DateTime), CAST(0x00009CD200000000 AS DateTime), N'CEO')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50000135', CAST(0x00009CD300000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime), N'CEO')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x00009EC200000000 AS DateTime), CAST(0x0000A13800000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50032466', CAST(0x0000A0DD00000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime), N'HOLDING')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A28600000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50016541', CAST(0x0000A14A00000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime), N'CEO_HR_ORG')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x0000A28700000000 AS DateTime), CAST(0x0000A3A700000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x0000A3A800000000 AS DateTime), CAST(0x0000A3A800000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x0000A3A900000000 AS DateTime), CAST(0x0000A45600000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[organizations] ([objCode], [begDate], [endDate], [longText]) VALUES (N'50043899', CAST(0x0000A45700000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime), N'CEO_HR_ORG_HRIS')
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50000135', N'50023726', CAST(0x0000943E00000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime))
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50015420', N'50016541', CAST(0x000090F300000000 AS DateTime), CAST(0x0000945600000000 AS DateTime))
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50016541', N'50043899', CAST(0x0000A14A00000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime))
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50023726', N'50016541', CAST(0x0000945700000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime))
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50032466', N'50000135', CAST(0x0000A0DD00000000 AS DateTime), CAST(0x002D247F00000000 AS DateTime))
INSERT [dbo].[relations] ([fatherCode], [begDate], [endDate]) VALUES (N'50042187', N'50043899', CAST(0x00009EC200000000 AS DateTime), CAST(0x0000A14900000000 AS DateTime))
答案 0 :(得分:1)
你可以试试这个......我不能说它会有更好的表现,但它会得到结果。
我首先在CTE上使用了所有(因此名称),但是你可能会在临时表中获得更好的性能,所以我使用了临时表。
您仍然需要添加6-12级。
DECLARE @datRif dateTime = convert(datetime, '20151231', 103)
SELECT COALESCE(r.objCode,o.objCode) objCode,
longText,
r.fatherCode
INTO #baseCTE
FROM dbo.organizations o
LEFT JOIN dbo.relations r ON o.objCode = r.objCode
AND @datRif BETWEEN r.begDate AND r.endDate
WHERE @datRif BETWEEN o.begDate AND o.endDate
;WITH recursiveCte AS
(
SELECT objCode,
longText,
fatherCode,
objCode AS [Root],
0 AS [Level]
FROM #baseCTE
UNION ALL
SELECT base.objCode,
base.longText,
base.fatherCode,
[Root],
[Level] + 1
FROM #baseCTE base
JOIN recursiveCte c ON c.fatherCode = base.objCode
)
SELECT *,
COUNT(*) OVER (PARTITION BY [Root]) Cnt,
ROW_NUMBER() OVER (PARTITION BY [Root] ORDER BY [Level] DESC) Rn
INTO #groupedCte
FROM recursiveCte
SELECT cte.longText,
cte.[Root] objRoot,
cte.objCode,
[root].objCode AS [root],
[root].longText AS [root desc],
cte.Cnt,
cte.Level,
ROW_NUMBER() OVER (PARTITION BY cte.Cnt ORDER BY cte.Rn) [order]
INTO #finalCte
FROM #groupedCte cte
JOIN (SELECT * FROM #groupedCte WHERE RN = 1) [root] ON [root].[Root] = cte.[Root]
WHERE cte.Rn <> 1
SELECT t.objRoot [object],
t.longText [object descr],
t.root,
t.[root desc],
uo1.objCode [uo1],
uo1.longText [uo1 desc],
uo2.objCode [uo2],
uo2.longText [uo2 desc],
uo3.objCode [uo3],
uo3.longText [uo3 desc],
uo4.objCode [uo4],
uo4.longText [uo4 desc],
uo5.objCode [uo5],
uo5.longText [uo5 desc]
FROM #finalCte t
OUTER APPLY(SELECT * FROM #finalCte f WHERE f.Cnt = t.Cnt AND f.[order] = 1 AND f.Level <> 0) uo1
OUTER APPLY(SELECT * FROM #finalCte f WHERE f.Cnt = t.Cnt AND f.[order] = 2 AND f.Level <> 0) uo2
OUTER APPLY(SELECT * FROM #finalCte f WHERE f.Cnt = t.Cnt AND f.[order] = 3 AND f.Level <> 0) uo3
OUTER APPLY(SELECT * FROM #finalCte f WHERE f.Cnt = t.Cnt AND f.[order] = 4 AND f.Level <> 0) uo4
OUTER APPLY(SELECT * FROM #finalCte f WHERE f.Cnt = t.Cnt AND f.[order] = 5 AND f.Level <> 0) uo5
WHERE t.Level = 0
ORDER BY t.Cnt DESC,
t.Level