对于大帖子感到抱歉。我试图将数据简化为核心问题。 我有2个表,有很多重复数据,我试图优化/完全重组。 我使用的是SQL Server 2008 R2
Menu
:
[Id] [int] IDENTITY(1,1) NOT NULL,
[ParentId] [int] NULL,
[Title] [varchar](50) NULL,
[ActionId] [int] NULL,
[Data] [varchar](500) NULL,
[FormId] [int] NULL,
RootMenu
:
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[FormId] [int] NULL,
示例数据
Menu
:
Id ParentId Title ActionId Data FormId
-- -------- ------ -------- ------------- ------
20 1 Title1 17 Data1Filter2 1
21 1 Title2 17 Data2Filter2 1
22 2 Title9 16 RootMenu2 1
23 2 Title5 17 Data3Filter2 1
24 3 Title1 17 Data1Filter2 2
25 3 Title2 17 Data2Filter2 2
26 4 Title9 16 RootMenu2 2
27 4 Title5 17 Data3Filter2 2
28 5 Title1 17 Data1Filter2 3
29 5 Title2 17 Data2Filter2X 3
30 6 Title9 16 RootMenu2 3
31 6 Title5 17 Data3Filter2 3
RootMenu
:
Id Name FormId
-- --------- ------
1 RootMenu2 1
2 RootMenu3 1
3 RootMenu2 2
4 RootMenu3 2
5 RootMenu2 3
6 RootMenu3 3
此示例中有3个表单,菜单层次结构如下所示:
创建了菜单结构(Form1
)
RootMenu3
Title9 -- as this action is 16 (recursive) it looks up RootMenu2 for Form 1, gets Id=1
Title1 (Data1Filter2) -- gets menu items with parentid =1
Title2 (Data2Filter2)
Title5
创建了菜单结构(Form2
)
RootMenu3
Title9 -- as this action is 16 (recursive) it looks up RootMenu2 for Form 2, gets Id=3
Title1 (Data1Filter2) -- gets menu items with parentid =3
Title2 (Data2Filter2)
Title5
创建了菜单结构(Form3
)
RootMenu3
Title9 -- as this action is 16 (recursive) it looks up RootMenu2 for Form 3, gets Id=5
Title1 (Data1Filter2) -- gets menu items with parentid =5
Title2 (Data2Filter2X)
Title5
Form1
和Form2
具有相同的层次结构,但Form3
不同(有Data2Filter2X
)
我需要的是SQL,它将为我提供独特的分层菜单结构。
我正在考虑将RootMenu
和Menu
表合并为1而不引用FormId
,并创建FormMenu
表:
CREATE TABLE [dbo].[FormMenu](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FormId] [int] NOT NULL,
[MenuId] [int] NOT NULL,
)
最终Menu
数据
Id ParentId Title ActionId Data
-- -------- ------ -------- -------------
20 1 Title1 17 Data1Filter2
21 1 Title2 17 Data2Filter2
22 2 Title9 16 RootMenu2
23 2 Title5 17 Data3Filter2
28 5 Title1 17 Data1Filter2
29 5 Title2 17 Data2Filter2X
30 6 Title9 16 RootMenu2_v2
31 6 Title5 17 Data3Filter2
1 null RootMenu2 1 null
2 null RootMenu3 1 null
5 null RootMenu2_v2 3 null
6 null RootMenu3_v2 3 null
最终FormMenu
数据
Id FormId MenuId
-- ------ ------
1 1 1
2 1 2
3 2 1
4 2 2
5 3 5
6 3 6
如果您已经读过这篇文章,谢谢。你可以帮我用SQL来获得最终结果吗?
答案 0 :(得分:0)
我不完全了解我已经完全理解了系统的所有规则,但似乎不需要“递归”(ActionId
= 16条记录);只包含简单关系(ActionId
= 17)的查询似乎产生了所需的输出:
测试数据:
DECLARE @menu TABLE
(
[Id] [INT] NOT NULL,
[ParentId] [INT] NULL,
[Title] [VARCHAR](50) NULL,
[ActionId] [INT] NULL,
[DATA] [VARCHAR](500) NULL,
[FormId] [INT] NULL
)
DECLARE @rootmenu TABLE
(
[Id] [INT] NOT NULL,
[Name] [VARCHAR](50) NULL,
[FormId] [INT] NULL
)
INSERT @menu (Id,ParentId,Title,ActionId,DATA,FormId)
SELECT 20,1,'Title1',17,'Data1Filter2',1
UNION SELECT 21,1,'Title2',17,'Data2Filter2',1
UNION SELECT 22,2,'Title9',16,'RootMenu2',1
UNION SELECT 23,2,'Title5',17,'Data3Filter2',1
UNION SELECT 24,3,'Title1',17,'Data1Filter2',2
UNION SELECT 25,3,'Title2',17,'Data2Filter2',2
UNION SELECT 26,4,'Title9',16,'RootMenu2',2
UNION SELECT 27,4,'Title5',17,'Data3Filter2',2
UNION SELECT 28,5,'Title1',17,'Data1Filter2',3
UNION SELECT 29,5,'Title2',17,'Data2Filter2X',3
UNION SELECT 30,6,'Title9',16,'RootMenu2',3
UNION SELECT 31,6,'Title5',17,'Data3Filter2',3
INSERT @rootmenu (Id,Name,FormId)
SELECT 1,'RootMenu2',1
UNION SELECT 2,'RootMenu3',1
UNION SELECT 3,'RootMenu2',2
UNION SELECT 4,'RootMenu3',2
UNION SELECT 5,'RootMenu2',3
UNION SELECT 6,'RootMenu3',3
查询:
SELECT DISTINCT m.FormId, r.Id AS MenuId
FROM @menu AS m
JOIN @rootmenu AS r
ON r.Id = m.ParentId
WHERE m.ActionId = 17
答案 1 :(得分:0)
我在这个答案中使用了Ed Harper的临时表脚本。 我第一次和第二次尝试获取要排除的行是不太正确的。第二次尝试的时间要长得多,但结果却是错误的。
在最终结果中,我认为我只想在排除表中获得parentid 3行,因为它们是parentid1行的副本。 然后我可以将它们从原始菜单表中排除。 我不希望排除表中的parentid 5行,因为菜单行与parentid 1的菜单行不同
DECLARE @menu TABLE
(
[Id] [INT] NOT NULL,
[ParentId] [INT] NULL,
[Title] [VARCHAR](50) NULL,
[ActionId] [INT] NULL,
[DATA] [VARCHAR](500) NULL,
[FormId] [INT] NULL
)
DECLARE @rootmenu TABLE
(
[Id] [INT] NOT NULL,
[Name] [VARCHAR](50) NULL,
[FormId] [INT] NULL
)
INSERT @menu (Id,ParentId,Title,ActionId,DATA,FormId)
SELECT 20,1,'Title1',17,'Data1Filter2',1
UNION SELECT 21,1,'Title2',17,'Data2Filter2',1
UNION SELECT 22,2,'Title9',16,'RootMenu2',1
UNION SELECT 23,2,'Title5',17,'Data3Filter2',1
UNION SELECT 24,3,'Title1',17,'Data1Filter2',2
UNION SELECT 25,3,'Title2',17,'Data2Filter2',2
UNION SELECT 26,4,'Title9',16,'RootMenu2',2
UNION SELECT 27,4,'Title5',17,'Data3Filter2',2
UNION SELECT 28,5,'Title1',17,'Data1Filter2',3
UNION SELECT 29,5,'Title2',17,'Data2Filter2X',3
UNION SELECT 30,6,'Title9',16,'RootMenu2',3
UNION SELECT 31,6,'Title5',17,'Data3Filter2',3
INSERT @rootmenu (Id,Name,FormId)
SELECT 1,'RootMenu2',1
UNION SELECT 2,'RootMenu3',1
UNION SELECT 3,'RootMenu3',2
UNION SELECT 4,'RootMenu3',2
UNION SELECT 5,'RootMenu3',3
UNION SELECT 6,'RootMenu3',4
--non recursive level 1 menu with Root
SELECT DISTINCT m.ParentId,m.Title,m.ActionId,m.DATA
FROM @menu AS m, @rootmenu AS r
where r.Id = m.ParentId
and m.ActionId<>16
--non recursive level 1 menu with Root
SELECT DISTINCT m.ParentId,m.Title,m.ActionId,m.DATA
FROM @menu AS m, @rootmenu AS r
where r.Id = m.ParentId
and m.ActionId=16
--level 1 menu without Root
--SELECT m.ParentId,m.Title,m.ActionId,m.DATA
--FROM @menu AS m
--level 1 count
SELECT ParentId, COUNT(*) as count from
(
SELECT ParentId as ParentId,Title as Title,ActionId as ActionId,DATA as DATA
FROM @menu m3) as l1
group by ParentId
--2nd level menu
SELECT DISTINCT m2.ParentId,m2.Title,m2.ActionId,m2.DATA
FROM @menu AS m, @menu AS m2, @rootmenu AS r,@rootmenu AS r2
where r.Id = m.ParentId
and r2.Id = m2.ParentId
and m.DATA= r2.Name
--initial attempt at exclusion rows
select distinct Level1.* from
(SELECT DISTINCT m2.ParentId as ParentId,m2.Title as Title,m2.ActionId as ActionId,m2.DATA as DATA
FROM @menu AS m, @menu AS m2, @rootmenu AS r,@rootmenu AS r2
where r.Id = m.ParentId
and r2.Id = m2.ParentId
and m.DATA= r2.Name)
as Level2 ,
(SELECT DISTINCT ParentId as ParentId,Title as Title,ActionId as ActionId,DATA as DATA
FROM @menu
where ActionId<>16)
as Level1
where Level1.Title=Level2.Title
and Level1.ActionId=Level2.ActionId
and Level1.DATA=Level2.DATA
and not Level1.ParentId=Level2.ParentId
--second attempt at exclusion rows with Counts
select distinct Level1.* from
(SELECT DISTINCT m2.ParentId as ParentId,m2.Title as Title,m2.ActionId as ActionId,m2.DATA as DATA
FROM @menu AS m, @menu AS m2, @rootmenu AS r,@rootmenu AS r2
where r.Id = m.ParentId
and r2.Id = m2.ParentId
and m.DATA= r2.Name)
as Level2
join
(SELECT ParentId, COUNT(*) as count from
(SELECT DISTINCT m2c.ParentId as ParentId,m2c.Title as Title,m2c.ActionId as ActionId,m2c.DATA as DATA from
@menu AS mc, @menu AS m2c, @rootmenu AS rc,@rootmenu AS r2c
where rc.Id = mc.ParentId
and r2c.Id = m2c.ParentId
and mc.DATA= r2c.Name) as l2
Group by ParentId) as L2Count
On L2Count.ParentId= Level2.ParentId,
(SELECT DISTINCT ParentId as ParentId,Title as Title,ActionId as ActionId,DATA as DATA
FROM @menu
where ActionId<>16)
as Level1
join
(SELECT ParentId, COUNT(*) as count from
(
SELECT ParentId as ParentId,Title as Title,ActionId as ActionId,DATA as DATA
FROM @menu m3
where ActionId<>16) as l1
group by ParentId) as L1Count
On L1Count.ParentId= Level1.ParentId
where Level1.Title=Level2.Title
and Level1.ActionId=Level2.ActionId
and Level1.DATA=Level2.DATA
and not Level1.ParentId=Level2.ParentId
and L1Count.count= L2Count.count