我之前的编辑有点混乱。希望这可以解决它......
TL / DR - 只需复制并执行两个脚本块,它就会变得明显。
我对级联数据有疑问。基本上我正在尝试根据某些预定义的条件(下面)在瀑布效果中向下移动数据。我已经解决了18个场景中的15个,我帮助了剩下的3个场景,GID是9,10和18。
从某种角度来看,在系统中,我正在处理数据,不断导入系统。数据稀少,我正在努力重建一整套数据以完成导入过程。我几乎无法控制系统中的数据形状,或者提供给我的数据: - /
最终问题是:我如何满足下面的5个级联规则,或者如何解决我在下面的脚本中提供的测试用例#18?
级联规则
在这个简化的场景中,级联的“规则”如下:
GID
)Seq
)IsLive
列将为1或0 IsLive = 1
然后向下移动数据,直到您遇到另一个IsLive = 1
或IsLive = 0
具有非空值IsLive = 0
然后向下移动数据,直到您点击另一个IsLive = 0
值。 注意:我的脚本是一个简化示例,但在完整方案中,我需要级联N
列。
解决方案说明
如果您运行下面的SQL,您将看到3列,输入,输出 - CTE的结果,预期 - 预期结果和结果 - 通过/失败。我已经包含了一个脚本,两者创建示例表并简单地通过执行来说明测试用例。
我希望有人可以提供帮助,如果不是,我可能不得不求助于SQL CLR SP解决方案。此外,我不依赖于此解决方案,您也可能完全放弃我的解决方案并提出新的解决方案。
测试用例
DECLARE @Test TABLE (GID int, Seq int, IsLive bit,
Eff date,
Name varchar(50),
Expected varchar(50)) -- expected val should help debug!
INSERT INTO @Test VALUES (1, 1, 1, '01-08-2012', 'RTS', 'RTS')
INSERT INTO @Test VALUES (1, 2, 0, '01-09-2012', 'RTA', 'RTA')
INSERT INTO @Test VALUES (1, 3, 1, '01-10-2012', 'FSA', 'RTA')
INSERT INTO @Test VALUES (1, 4, 0, '01-11-2012', NULL, 'RTA')
INSERT INTO @Test VALUES (1, 5, 1, '01-12-2012', 'FSA', 'RTA')
INSERT INTO @Test VALUES (2, 1, 1, '01-08-2012', 'RTS', 'RTS')
INSERT INTO @Test VALUES (2, 2, 0, '01-09-2012', 'RTA', 'RTA')
INSERT INTO @Test VALUES (2, 3, 1, '01-10-2012', 'FSA', 'RTA')
INSERT INTO @Test VALUES (2, 4, 0, '01-11-2012', 'GSM', 'GSM')
INSERT INTO @Test VALUES (2, 5, 1, '01-12-2012', 'FSA', 'GSM')
INSERT INTO @Test VALUES (3, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO @Test VALUES (3, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO @Test VALUES (4, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 2, 0, '01-02-2012', 'FSA', 'FSA')
INSERT INTO @Test VALUES (4, 3, 0, '01-03-2012', NULL, 'FSA')
INSERT INTO @Test VALUES (5, 1, 0, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 2, 1, '01-02-2012', 'LSI', 'LSI')
INSERT INTO @Test VALUES (5, 3, 0, '01-03-2012', NULL, 'LSI')
INSERT INTO @Test VALUES (6, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 2, 0, '01-02-2012', 'LSI', 'LSI')
INSERT INTO @Test VALUES (6, 3, 1, '01-03-2012', NULL, 'LSI')
INSERT INTO @Test VALUES (7, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO @Test VALUES (7, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO @Test VALUES (7, 3, 1, '01-03-2012', 'RTA', 'RTA')
INSERT INTO @Test VALUES (8, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO @Test VALUES (8, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO @Test VALUES (8, 3, 1, '01-03-2012', NULL, NULL)
INSERT INTO @Test VALUES (9, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO @Test VALUES (9, 2, 1, '01-02-2012', NULL, NULL)
INSERT INTO @Test VALUES (9, 3, 1, '01-03-2012', 'RTS', 'RTS')
INSERT INTO @Test VALUES (10, 1, 1, '01-01-2012', 'FSA','FSA')
INSERT INTO @Test VALUES (10, 2, 1, '01-02-2012', 'GSM','GSM')
INSERT INTO @Test VALUES (10, 3, 1, '01-03-2012', 'RTS','RTS')
INSERT INTO @Test VALUES (11, 1, 0, '01-01-2012', 'NOP','NOP')
INSERT INTO @Test VALUES (11, 2, 1, '01-02-2012', 'TAP','NOP')
INSERT INTO @Test VALUES (11, 3, 1, '01-03-2012', 'STG','NOP')
INSERT INTO @Test VALUES (12, 1, 1, '01-01-2012', 'RTS','RTS')
INSERT INTO @Test VALUES (12, 2, 0, '01-02-2012', 'RTM','RTM')
INSERT INTO @Test VALUES (12, 3, 1, '01-03-2012', 'LSA','RTM')
INSERT INTO @Test VALUES (12, 4, 1, '01-03-2012', 'LSA','RTM')
INSERT INTO @Test VALUES (12, 5, 1, '01-03-2012', 'GSM','RTM')
INSERT INTO @Test VALUES (13, 1, 1, '01-08-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (13, 2, 0, '01-09-2012', NULL, 'BAR')
INSERT INTO @Test VALUES (13, 3, 1, '01-10-2012', 'TST','TST')
INSERT INTO @Test VALUES (14, 1, 1, '01-08-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (14, 2, 0, '01-09-2012', 'GIP','GIP')
INSERT INTO @Test VALUES (14, 3, 1, '01-10-2012', 'TST','GIP')
INSERT INTO @Test VALUES (15, 1, 1, '01-01-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (15, 2, 0, '01-02-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (15, 3, 1, '01-02-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (15, 4, 1, '01-02-2012', 'GYM','BAR')
INSERT INTO @Test VALUES (16, 1, 1, '01-02-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (16, 2, 0, '01-03-2012', NULL, 'BAR')
INSERT INTO @Test VALUES (16, 3, 1, '01-03-2012', 'BAR','BAR')
INSERT INTO @Test VALUES (16, 4, 1, '01-03-2012', 'GYM','GYM')
INSERT INTO @Test VALUES (17, 1, 1, '01-02-2012', 'BAR', 'BAR')
INSERT INTO @Test VALUES (17, 2, 0, '01-03-2012', 'GIP', 'GIP')
INSERT INTO @Test VALUES (17, 3, 0, '01-03-2012', NULL, 'GIP')
INSERT INTO @Test VALUES (17, 4, 1, '01-03-2012', 'TST', 'GIP')
-- -------------------------------------------
-- Following is the GID=18 test case that fails
-- -------------------------------------------
INSERT INTO @Test VALUES (18, 1, 1, '01-02-2012', 'BAR', 'BAR')
INSERT INTO @Test VALUES (18, 2, 0, '01-03-2012', 'BAR', 'BAR')
INSERT INTO @Test VALUES (18, 3, 0, '01-03-2012', NULL, 'BAR')
INSERT INTO @Test VALUES (18, 4, 1, '01-03-2012', 'TST', 'BAR')
解决方案
DECLARE @PrevNonLiveSeq int = NULL
;WITH CTE AS (
SELECT T.GID, T.SEQ, T.IsLive, Expected
, Name AS Name
, CASE WHEN T.IsLive = 0 THEN T.SEQ ELSE NULL END As PrevNonLiveSeq
, CASE WHEN T.IsLive = 1 THEN T.SEQ ELSE NULL END As PrevLiveSeq
, NULL AS PerNonLiveSeqCalc
, NULL AS PerLiveSeqCalc
, 0 PrevSeq
, CAST(NULL AS varchar(50)) PrevName
FROM @Test T
WHERE T.Seq = 1
UNION ALL
SELECT Curr.GID, Curr.SEQ, Curr.IsLive, Curr.Expected
,CASE WHEN Curr.IsLive = 0 THEN ISNULL(Curr.Name, Prev.Name)
ELSE CASE WHEN PrevNonLive.Name IS NULL THEN
CASE WHEN Prev.Name <> PrevLive.Name THEN Prev.Name ELSE Curr.Name END
ELSE Prev.Name END
END
,CASE WHEN Curr.IsLive = 0 THEN Curr.SEQ ELSE Prev.PrevNonLiveSeq END As PrevNonLiveSeq
,CASE WHEN Curr.IsLive = 1 THEN Curr.SEQ ELSE Prev.PrevLiveSeq END As PrevLiveSeq
, ISNULL(Prev.PrevNonLiveSeq, Curr.SEQ) AS PerNonLiveSeqCalc
, ISNULL(Prev.PrevLiveSeq, Curr.SEQ) AS PerLiveSeqCalc
, Prev.Seq PrevSeq, Prev.Name PrevName
FROM CTE Prev
JOIN @Test Curr ON Curr.GID = Prev.GID AND Curr.SEQ = Prev.SEQ+1
JOIN @Test PrevNonLive ON Prev.GID = PrevNonLive.GID AND PrevNonLive.SEQ = ISNULL(Prev.PrevNonLiveSeq, Curr.SEQ)
JOIN @Test PrevLive ON Prev.GID = PrevLive.GID AND PrevLive.SEQ = ISNULL(Prev.PrevLiveSeq, Curr.SEQ)
)
SELECT CTE.GID, CTE.Seq, T.IsLive
, T.Name Input, CTE.Name [Output]
, CASE WHEN CTE.Name = CTE.Expected OR (CTE.Name IS NULL AND CTE.Expected IS NULL) THEN 'Pass' ELSE 'FAIL' END AS Result
, CTE.Expected
FROM CTE
INNER JOIN @Test T on CTE.GID = T.GID AND CTE.Seq = T.Seq
ORDER BY CTE.GID, CTE.Seq
结果请复制并在SSMS中运行
谢谢!
答案 0 :(得分:1)
这应该有效,不需要递归CTE。您只需要为想要“级联”的每个实际字段执行COALESCE。
SELECT crrnt.*, COALESCE(cscd.Name, crrnt.Name) AS [Output]
FROM @Test crrnt
OUTER APPLY (
SELECT TOP 1 *
FROM @Test prir
WHERE prir.GID = crrnt.GID
AND prir.Seq < crrnt.Seq
AND (
(
crrnt.IsLive = 1
AND prir.IsLive = 0
AND prir.Name IS NOT NULL
)
OR (
crrnt.IsLive = 0
AND crrnt.Name IS NULL
AND (
(
prir.IsLive = 0
AND prir.Name IS NOT NULL
)
OR (
prir.IsLive = 1
AND NOT EXISTS(
SELECT *
FROM @Test confirm
WHERE confirm.GID = prir.GID
AND confirm.Seq < prir.Seq
AND confirm.IsLive = 0
AND confirm.Name IS NOT NULL
)
)
)
)
)
ORDER BY prir.Seq DESC
) cscd
修改强>
测试查询的性能通常是一个好主意,所以以下就是这样。测试包括:
1.从最初发布的查询和样本数据开始
2.将临时变量更改为临时表(查询将最终达到真实用户表)
3.在临时表上创建聚集索引,为:GID,Seq。
4.复制数据,但GID值较高(将18行转为6,300,063行)
5.使用DBCC FREEPROCCACAHE和DBCC DROPCLEANBUFFERS确保平等的环境
6.使用STATISTICS IO和STATISTICS TIME
SET NOCOUNT ON
-- DROP TABLE #Test
IF (OBJECT_ID('tempdb.dbo.#Test') IS NULL)
BEGIN
CREATE TABLE #Test (GID INT NOT NULL, Seq INT NOT NULL, IsLive BIT NOT NULL,
Eff date,
Name varchar(50),
Expected varchar(50), -- expected val should help debug!
PRIMARY KEY(GID, Seq)
)
INSERT INTO #Test VALUES (1, 1, 1, '01-08-2012', 'RTS', 'RTS')
INSERT INTO #Test VALUES (1, 2, 0, '01-09-2012', 'RTA', 'RTA')
INSERT INTO #Test VALUES (1, 3, 1, '01-10-2012', 'FSA', 'RTA')
INSERT INTO #Test VALUES (1, 4, 0, '01-11-2012', NULL, 'RTA')
INSERT INTO #Test VALUES (1, 5, 1, '01-12-2012', 'FSA', 'RTA')
INSERT INTO #Test VALUES (2, 1, 1, '01-08-2012', 'RTS', 'RTS')
INSERT INTO #Test VALUES (2, 2, 0, '01-09-2012', 'RTA', 'RTA')
INSERT INTO #Test VALUES (2, 3, 1, '01-10-2012', 'FSA', 'RTA')
INSERT INTO #Test VALUES (2, 4, 0, '01-11-2012', 'GSM', 'GSM')
INSERT INTO #Test VALUES (2, 5, 1, '01-12-2012', 'FSA', 'GSM')
INSERT INTO #Test VALUES (3, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO #Test VALUES (3, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO #Test VALUES (4, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO #Test VALUES (4, 2, 0, '01-02-2012', 'FSA', 'FSA')
INSERT INTO #Test VALUES (4, 3, 0, '01-03-2012', NULL, 'FSA')
INSERT INTO #Test VALUES (5, 1, 0, '01-01-2012', NULL, NULL)
INSERT INTO #Test VALUES (5, 2, 1, '01-02-2012', 'LSI', 'LSI')
INSERT INTO #Test VALUES (5, 3, 0, '01-03-2012', NULL, 'LSI')
INSERT INTO #Test VALUES (6, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO #Test VALUES (6, 2, 0, '01-02-2012', 'LSI', 'LSI')
INSERT INTO #Test VALUES (6, 3, 1, '01-03-2012', NULL, 'LSI')
INSERT INTO #Test VALUES (7, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO #Test VALUES (7, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO #Test VALUES (7, 3, 1, '01-03-2012', 'RTA', 'RTA')
INSERT INTO #Test VALUES (8, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO #Test VALUES (8, 2, 0, '01-02-2012', NULL, 'FSA')
INSERT INTO #Test VALUES (8, 3, 1, '01-03-2012', NULL, NULL)
INSERT INTO #Test VALUES (9, 1, 1, '01-01-2012', 'FSA', 'FSA')
INSERT INTO #Test VALUES (9, 2, 1, '01-02-2012', NULL, NULL)
INSERT INTO #Test VALUES (9, 3, 1, '01-03-2012', 'RTS', 'RTS')
INSERT INTO #Test VALUES (10, 1, 1, '01-01-2012', 'FSA','FSA')
INSERT INTO #Test VALUES (10, 2, 1, '01-02-2012', 'GSM','GSM')
INSERT INTO #Test VALUES (10, 3, 1, '01-03-2012', 'RTS','RTS')
INSERT INTO #Test VALUES (11, 1, 0, '01-01-2012', 'NOP','NOP')
INSERT INTO #Test VALUES (11, 2, 1, '01-02-2012', 'TAP','NOP')
INSERT INTO #Test VALUES (11, 3, 1, '01-03-2012', 'STG','NOP')
INSERT INTO #Test VALUES (12, 1, 1, '01-01-2012', 'RTS','RTS')
INSERT INTO #Test VALUES (12, 2, 0, '01-02-2012', 'RTM','RTM')
INSERT INTO #Test VALUES (12, 3, 1, '01-03-2012', 'LSA','RTM')
INSERT INTO #Test VALUES (12, 4, 1, '01-03-2012', 'LSA','RTM')
INSERT INTO #Test VALUES (12, 5, 1, '01-03-2012', 'GSM','RTM')
INSERT INTO #Test VALUES (13, 1, 1, '01-08-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (13, 2, 0, '01-09-2012', NULL, 'BAR')
INSERT INTO #Test VALUES (13, 3, 1, '01-10-2012', 'TST','TST')
INSERT INTO #Test VALUES (14, 1, 1, '01-08-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (14, 2, 0, '01-09-2012', 'GIP','GIP')
INSERT INTO #Test VALUES (14, 3, 1, '01-10-2012', 'TST','GIP')
INSERT INTO #Test VALUES (15, 1, 1, '01-01-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (15, 2, 0, '01-02-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (15, 3, 1, '01-02-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (15, 4, 1, '01-02-2012', 'GYM','BAR')
INSERT INTO #Test VALUES (16, 1, 1, '01-02-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (16, 2, 0, '01-03-2012', NULL, 'BAR')
INSERT INTO #Test VALUES (16, 3, 1, '01-03-2012', 'BAR','BAR')
INSERT INTO #Test VALUES (16, 4, 1, '01-03-2012', 'GYM','GYM')
INSERT INTO #Test VALUES (17, 1, 1, '01-02-2012', 'BAR', 'BAR')
INSERT INTO #Test VALUES (17, 2, 0, '01-03-2012', 'GIP', 'GIP')
INSERT INTO #Test VALUES (17, 3, 0, '01-03-2012', NULL, 'GIP')
INSERT INTO #Test VALUES (17, 4, 1, '01-03-2012', 'TST', 'GIP')
-- -------------------------------------------
-- Following is the GID=18 test case that fails
-- -------------------------------------------
INSERT INTO #Test VALUES (18, 1, 1, '01-02-2012', 'BAR', 'BAR')
INSERT INTO #Test VALUES (18, 2, 0, '01-03-2012', 'BAR', 'BAR')
INSERT INTO #Test VALUES (18, 3, 0, '01-03-2012', NULL, 'BAR')
INSERT INTO #Test VALUES (18, 4, 1, '01-03-2012', 'TST', 'BAR')
CHECKPOINT
INSERT INTO #Test (GID, Seq, IsLive, Eff, Name, Expected)
SELECT tmp.GID + (multiplier.Num * 20) AS [GID], tmp.Seq, tmp.IsLive, tmp.Eff, tmp.Name, tmp.Expected
FROM #Test tmp
CROSS JOIN (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [Num]
FROM master.sys.objects so1
CROSS JOIN master.sys.objects so2
CROSS JOIN master.sys.objects so3
) multiplier
WHERE multiplier.Num <= 100000
CHECKPOINT
SELECT COUNT(*) FROM #Test
ALTER INDEX ALL ON #Test REBUILD
-- SELECT TOP 1000 * FROM #Test ORDER BY GID, Seq
END /* IF (OBJECT_ID('tempdb.dbo.#Test') IS NULL) */
-----------------------------------------------------------------------------
DBCC FREEPROCCACHE WITH NO_INFOMSGS
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS
PRINT '-- Original solution (Recursive CTE):'
PRINT ''
SET STATISTICS IO ON
SET STATISTICS TIME ON
;WITH CTE AS (
SELECT T.GID, T.SEQ, T.IsLive, Expected
, Name AS Name
, CASE WHEN T.IsLive = 0 THEN T.SEQ ELSE NULL END As PrevNonLiveSeq
, CASE WHEN T.IsLive = 1 THEN T.SEQ ELSE NULL END As PrevLiveSeq
, NULL AS PerNonLiveSeqCalc
, NULL AS PerLiveSeqCalc
, 0 PrevSeq
, CAST(NULL AS varchar(50)) PrevName
FROM #Test T
WHERE T.Seq = 1
UNION ALL
SELECT Curr.GID, Curr.SEQ, Curr.IsLive, Curr.Expected
,CASE WHEN Curr.IsLive = 0 THEN ISNULL(Curr.Name, Prev.Name)
ELSE CASE WHEN PrevNonLive.Name IS NULL THEN
CASE WHEN Prev.Name <> PrevLive.Name THEN Prev.Name ELSE Curr.Name END
ELSE Prev.Name END
END
,CASE WHEN Curr.IsLive = 0 THEN Curr.SEQ ELSE Prev.PrevNonLiveSeq END As PrevNonLiveSeq
,CASE WHEN Curr.IsLive = 1 THEN Curr.SEQ ELSE Prev.PrevLiveSeq END As PrevLiveSeq
, ISNULL(Prev.PrevNonLiveSeq, Curr.SEQ) AS PerNonLiveSeqCalc
, ISNULL(Prev.PrevLiveSeq, Curr.SEQ) AS PerLiveSeqCalc
, Prev.Seq PrevSeq, Prev.Name PrevName
FROM CTE Prev
JOIN #Test Curr ON Curr.GID = Prev.GID AND Curr.SEQ = Prev.SEQ+1
JOIN #Test PrevNonLive ON Prev.GID = PrevNonLive.GID AND PrevNonLive.SEQ = ISNULL(Prev.PrevNonLiveSeq, Curr.SEQ)
JOIN #Test PrevLive ON Prev.GID = PrevLive.GID AND PrevLive.SEQ = ISNULL(Prev.PrevLiveSeq, Curr.SEQ)
)
SELECT CTE.GID, CTE.Seq, T.IsLive
, T.Name Input, CTE.Name [Output]
, CASE WHEN CTE.Name = CTE.Expected OR (CTE.Name IS NULL AND CTE.Expected IS NULL) THEN 'Pass' ELSE 'FAIL' END AS Result
, CTE.Expected
FROM CTE
INNER JOIN #Test T on CTE.GID = T.GID AND CTE.Seq = T.Seq
ORDER BY CTE.GID, CTE.Seq
SET STATISTICS TIME OFF
SET STATISTICS IO OFF
PRINT '=================================================='
------------------------------------------------------
DBCC FREEPROCCACHE WITH NO_INFOMSGS
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS
PRINT '-- Proposed solution (OUTER APPLY):'
PRINT ''
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT crrnt.GID, crrnt.Seq, crrnt.IsLive,
COALESCE(cscd.Name, crrnt.Name) AS [Output],
CASE
WHEN COALESCE(COALESCE(cscd.Name, crrnt.Name), '~~~') = COALESCE(crrnt.Expected, '~~~') THEN 'Pass'
ELSE 'FAIL'
END AS [Result],
crrnt.Expected
FROM #Test crrnt
OUTER APPLY (
SELECT TOP 1 *
FROM #Test prir
WHERE prir.GID = crrnt.GID
AND prir.Seq < crrnt.Seq
AND (
(
crrnt.IsLive = 1
AND prir.IsLive = 0
AND prir.Name IS NOT NULL
)
OR (
crrnt.IsLive = 0
AND crrnt.Name IS NULL
AND (
(
prir.IsLive = 0
AND prir.Name IS NOT NULL
)
OR (
prir.IsLive = 1
AND NOT EXISTS(
SELECT *
FROM #Test confirm
WHERE confirm.GID = prir.GID
AND confirm.Seq < prir.Seq
AND confirm.IsLive = 0
AND confirm.Name IS NOT NULL
)
)
)
)
)
ORDER BY prir.Seq DESC
) cscd
SET STATISTICS TIME OFF
SET STATISTICS IO OFF
-----------------------------------
我执行上述测试显示:
因此,原始查询对于CPU和已用时间来说慢约3.5倍,并且逻辑读取比我提出的查询多约5倍。小心递归CTE; - )。