【发布时间】:2019-11-02 09:01:05
【问题描述】:
我有一个名为 WorkSpace 的表,有 4 列。
此表中的每条记录通过Parent_id 列引用它们的父记录。
您应该继续这个循环,直到您到达主要父级以及View_Parent_id 列中指定的所有这些步骤。
主父编号的ID由1指定。
所以现在我想创建一个NEW_WorkSpace 表并将View_Parent_id 列中的每个值分隔到一个单独的列中。
View_Parent_id 列最终值为 15,因此我们需要新表中的 15 列 (Level_1...Level_15)。
我在查询中使用了循环,但速度很慢。
WorkSpace 表有 150 万行。
WorkSpace表:
+-----+-------+-----------+------------------+
| W_ID| Title | Parent_id | View_Parent_id |
+-----+-------+-----------+------------------+
| 1 | AAA | null | null |
| 2 | BV | 1 | 1 |
| 3 | CX | 2 | 1+2 |
| 4 | DSO | 2 | 1+2 |
| 5 | ER | 3 | 1+2+3 |
| 6 | ER | 5 | 1+2+3+5 |
| ... | ... | ... | ... |
| 1000| MNV | 1 | 1 |
| 1001| SF | 1000 | 1+1000 |
| 1002| EDD | 1000 | 1+1000 |
| 1003| YSG | 1001 | 1+1000+1001 |
| 1004| RPO | 1003 | 1+1000+1001+1003 |
+-----+-------+-----------+------------------+
NEW_WorkSpace表:
+-----+-------+-----------+---------+---------+---------+-----+----------+
| ID | W_id | Parent_id | Level_1 | Level_2 | Level_3 | ... | Level_15 |
+-----+-------+-----------+---------+-------- +---------+-----+----------+
| 100 | 1 | null | AAA | | | ... | |
| 101 | 2 | 1 | AAA | BV | | ... | |
| 102 | 3 | 2 | AAA | BV | | ... | |
| 103 | 4 | 2 | AAA | BV | CX | ... | |
| 104 | 5 | 3 | AAA | BV | CX | ... | |
| ... | ... | ... | ... | ... | ... | ... | ... |
+-----+-------+-----------+---------+---------+---------+-----+----------+
我的代码:
BEGIN
DECLARE @W_ID decimal(20, 0);
DECLARE @parent_id decimal(20, 0);
DECLARE @Level1 nvarchar(MAX);
DECLARE @Level2 nvarchar(MAX);
DECLARE @Level3 nvarchar(MAX);
DECLARE @Level4 nvarchar(MAX);
DECLARE @Level5 nvarchar(MAX);
DECLARE @Level6 nvarchar(MAX);
DECLARE @Level7 nvarchar(MAX);
DECLARE @Level8 nvarchar(MAX);
DECLARE @Level9 nvarchar(MAX);
DECLARE @Level10 nvarchar(MAX);
DECLARE @Level11 nvarchar(MAX);
DECLARE @Level12 nvarchar(MAX);
DECLARE @Level13 nvarchar(MAX);
DECLARE @Level14 nvarchar(MAX);
DECLARE @Level15 nvarchar(MAX);
DECLARE @titles_tmp nvarchar(MAX);
DECLARE @cont_spilit_tittle int;
DECLARE @parent_titles_tmp nvarchar(MAX);
DECLARE @cont_tmp int;
DECLARE @cont int;
SELECT @cont = COUNT(*) FROM dbo.WorkSpace ;
SET @cont_tmp = 0;
WHILE (@cont_tmp < @cont)
BEGIN
SET @W_ID = (SELECT dbo.WorkSpace.W_ID FROM dbo.WorkSpace
ORDER BY W_ID ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
SET @parent_id = (SELECT dbo.WorkSpace.parent_id FROM dbo.WorkSpace
ORDER BY W_ID ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
SET @titles_tmp = (SELECT dbo.WorkSpace.title FROM dbo.WorkSpace
ORDER BY W_ID ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
SET @parent_titles_tmp = (SELECT dbo.WorkSpace.parent_titles FROM dbo.WorkSpace
ORDER BY W_ID ASC OFFSET @cont_tmp ROWS FETCH NEXT 1 ROWS ONLY)
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
DROP TABLE #MyTempTable
SELECT IDENTITY(INT, 1, 1) AS 'RowID', *
INTO #MyTempTable
FROM StringSplitXML(@parent_titles_tmp, '+')
INSERT INTO #MyTempTable
VALUES (@titles_tmp)
SET @cont_spilit_tittle = (SELECT COUNT(*) FROM #MyTempTable)
IF(@cont_spilit_tittle < 0)
SET @cont_spilit_tittle = 1
WHILE (@cont_spilit_tittle < 15)
BEGIN
INSERT INTO #MyTempTable VALUES ('')
SET @cont_spilit_tittle = CAST(@cont_spilit_tittle AS INT) + 1
END
SET @Level1 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level2 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level3 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level4 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 3 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level5 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 4 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level6 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 5 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level7 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 6 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level8 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 7 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level9 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 8 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level10 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 9 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level11 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 10 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level12 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 11 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level13 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 12 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level14 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 13 ROWS FETCH NEXT 1 ROWS ONLY)
SET @Level15 = (SELECT Value FROM #MyTempTable
ORDER BY RowID ASC OFFSET 14 ROWS FETCH NEXT 1 ROWS ONLY)
INSERT INTO [].[dbo].[NEW_WorkSpace]
([W_ID], [parent_id],
[Level1], [Level2], [Level3], [Level4], [Level5],
[Level6], [Level7], [Level8], [Level9], [Level10],
[Level11], [Level12], [Level13], [Level14], [Level15])
VALUES (@W_ID, @parent_id,
@Level1, @Level2, @Level3, @Level4, @Level5,
@Level6, @Level7, @Level8, @Level9, @Level10,
@Level11, @Level12, @Level13, @Level14, @Level15)
SET @cont_tmp = CAST(@cont_tmp AS INT) + 1
END
RETURN
END
感谢您的帮助。
【问题讨论】:
-
请向我们展示您的尝试
-
@squirrel 代码已添加。
-
正如您提到的 pivote,但在查看您的代码和输出时没有 pivote 概念??
-
@nits-patel 我只是猜测它可能是枢轴的解决方案,但我没有自己写
-
是的,因为
WHILE是在 SQL 中做任何事情的最糟糕的方法之一;它不是一种编程语言。查询语言中的WHILE本来就很慢。
标签: sql sql-server sql-server-2014