SQL 服务器 - 选择如何在树的顶层传播值时? (包括SQLFiddle)
SQL Server - When selecting how to propagate values on the top level of a tree? (SQL Fiddle included)
我需要在树的顶层传播值:
CREATE TABLE [dbo].[area](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[parent_id] [int] NULL,
[color] [varchar](50) NULL,
[priority] [int] NULL)
insert into area values('root', NULL, NULL, NULL);
insert into area values('test1', 1, NULL, NULL);
insert into area values('test2', 2, 'red', 50);
insert into area values('test3', 5, 'blue', 1);
insert into area values('test4', 1, 'yellow', 10);
id
parent_id
name
color
priority
level
path_id
path_name
1
(null)
root
(null)
(null)
0
1
root
2
1
test1
(null)
(null)
1
1
root\test1
5
1
test4
yellow
10
1
1
root\test4
4
5
test3
blue
1
2
1
root\test4\test3
3
2
test2
red
50
2
1
root\test1\test2
我正在使用以下查询执行此操作(下一个过程使用 CTE):
WITH tPATH
AS (SELECT id,
parent_id,
name,
color,
priority,
0 as [level],
CAST(id AS NVARCHAR(MAX)) As path_id,
CAST(name AS NVARCHAR(MAX)) As path_name
FROM area
WHERE parent_id is NULL
UNION ALL
SELECT area.id,
area.parent_id,
area.name,
area.color,
area.priority,
[level] + 1,
CONCAT(tPATH.path_id, '\', CAST(area.id AS NVARCHAR(MAX))),
CONCAT(tPATH.path_name, '\', CAST(area.name AS NVARCHAR(MAX)))
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
)
select *
from tPATH;
优先级 1 最好。所以我想要这个:
- blue 必须在 id 1 中,优先级为 1,
- red 必须在 id 2 中,优先级为 50,
- blue 必须在 id 5 中,优先级为 1,
- id 4和3保持不变
id
parent_id
name
color
priority
level
path_id
path_name
1
(null)
root
blue
1
0
1
root
2
1
test1
red
50
1
1
root\test1
5
1
test4
blue
1
1
1
root\test4
4
5
test3
blue
1
2
1
root\test4\test3
3
2
test2
red
50
2
1
root\test1\test2
有什么想法吗(在顶层传播颜色和优先级)? The fiddle || SQLize
提前致谢。
您可以使用查询
计算一个有效优先级作为所有节点后代的最小值
WITH tPATH
AS (SELECT id,
id [top],
parent_id,
priority
FROM area
UNION ALL
SELECT area.id,
[top],
area.parent_id,
area.priority
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
)
select [top] as id, min(priority) effective_priority
from tPATH
group by [top];
根据@Serg 的回答,我创建了这段代码,它给了我预期的结果。能再简单点吗?
WITH tPATH
AS (SELECT id,
parent_id,
name,
color,
priority,
0 [level],
CAST(id AS NVARCHAR(MAX)) [path_id],
CAST(name AS NVARCHAR(MAX)) [path_name]
FROM area
WHERE parent_id is NULL
UNION ALL
SELECT area.id,
area.parent_id,
area.name,
area.color,
area.priority,
[level] + 1,
CONCAT(tPATH.path_id, '\', CAST(area.id AS NVARCHAR(MAX))),
CONCAT(tPATH.path_name, '\', CAST(area.name AS NVARCHAR(MAX)))
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
),
tDIFF
AS (SELECT id,
id [top],
parent_id,
priority
FROM area
UNION ALL
SELECT area.id,
[top],
area.parent_id,
area.priority
FROM area
INNER JOIN tDIFF
ON area.parent_id = tDIFF.id
),
tDIFFEND
AS (select [top] as id,
min(priority) effective_priority
from tDIFF
group by [top]
)
SELECT tPATH.id,
tPATH.parent_id,
tPATH.name,
area.color,
effective_priority [priority],
tPATH.level,
tPATH.path_id,
tPATH.path_name
from tPATH
INNER JOIN tDIFFEND
ON tDIFFEND.id = tPATH.id
LEFT JOIN area
ON area.priority = effective_priority;
我需要在树的顶层传播值:
CREATE TABLE [dbo].[area](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[parent_id] [int] NULL,
[color] [varchar](50) NULL,
[priority] [int] NULL)
insert into area values('root', NULL, NULL, NULL);
insert into area values('test1', 1, NULL, NULL);
insert into area values('test2', 2, 'red', 50);
insert into area values('test3', 5, 'blue', 1);
insert into area values('test4', 1, 'yellow', 10);
id | parent_id | name | color | priority | level | path_id | path_name |
---|---|---|---|---|---|---|---|
1 | (null) | root | (null) | (null) | 0 | 1 | root |
2 | 1 | test1 | (null) | (null) | 1 | 1 | root\test1 |
5 | 1 | test4 | yellow | 10 | 1 | 1 | root\test4 |
4 | 5 | test3 | blue | 1 | 2 | 1 | root\test4\test3 |
3 | 2 | test2 | red | 50 | 2 | 1 | root\test1\test2 |
我正在使用以下查询执行此操作(下一个过程使用 CTE):
WITH tPATH
AS (SELECT id,
parent_id,
name,
color,
priority,
0 as [level],
CAST(id AS NVARCHAR(MAX)) As path_id,
CAST(name AS NVARCHAR(MAX)) As path_name
FROM area
WHERE parent_id is NULL
UNION ALL
SELECT area.id,
area.parent_id,
area.name,
area.color,
area.priority,
[level] + 1,
CONCAT(tPATH.path_id, '\', CAST(area.id AS NVARCHAR(MAX))),
CONCAT(tPATH.path_name, '\', CAST(area.name AS NVARCHAR(MAX)))
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
)
select *
from tPATH;
优先级 1 最好。所以我想要这个:
- blue 必须在 id 1 中,优先级为 1,
- red 必须在 id 2 中,优先级为 50,
- blue 必须在 id 5 中,优先级为 1,
- id 4和3保持不变
id | parent_id | name | color | priority | level | path_id | path_name |
---|---|---|---|---|---|---|---|
1 | (null) | root | blue | 1 | 0 | 1 | root |
2 | 1 | test1 | red | 50 | 1 | 1 | root\test1 |
5 | 1 | test4 | blue | 1 | 1 | 1 | root\test4 |
4 | 5 | test3 | blue | 1 | 2 | 1 | root\test4\test3 |
3 | 2 | test2 | red | 50 | 2 | 1 | root\test1\test2 |
有什么想法吗(在顶层传播颜色和优先级)? The fiddle || SQLize
提前致谢。
您可以使用查询
计算一个有效优先级作为所有节点后代的最小值WITH tPATH
AS (SELECT id,
id [top],
parent_id,
priority
FROM area
UNION ALL
SELECT area.id,
[top],
area.parent_id,
area.priority
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
)
select [top] as id, min(priority) effective_priority
from tPATH
group by [top];
根据@Serg 的回答,我创建了这段代码,它给了我预期的结果。能再简单点吗?
WITH tPATH
AS (SELECT id,
parent_id,
name,
color,
priority,
0 [level],
CAST(id AS NVARCHAR(MAX)) [path_id],
CAST(name AS NVARCHAR(MAX)) [path_name]
FROM area
WHERE parent_id is NULL
UNION ALL
SELECT area.id,
area.parent_id,
area.name,
area.color,
area.priority,
[level] + 1,
CONCAT(tPATH.path_id, '\', CAST(area.id AS NVARCHAR(MAX))),
CONCAT(tPATH.path_name, '\', CAST(area.name AS NVARCHAR(MAX)))
FROM area
INNER JOIN tPATH
ON area.parent_id = tPATH.id
),
tDIFF
AS (SELECT id,
id [top],
parent_id,
priority
FROM area
UNION ALL
SELECT area.id,
[top],
area.parent_id,
area.priority
FROM area
INNER JOIN tDIFF
ON area.parent_id = tDIFF.id
),
tDIFFEND
AS (select [top] as id,
min(priority) effective_priority
from tDIFF
group by [top]
)
SELECT tPATH.id,
tPATH.parent_id,
tPATH.name,
area.color,
effective_priority [priority],
tPATH.level,
tPATH.path_id,
tPATH.path_name
from tPATH
INNER JOIN tDIFFEND
ON tDIFFEND.id = tPATH.id
LEFT JOIN area
ON area.priority = effective_priority;