我有三个表:两个分层表和这些表之间的一个联结。
Teams
id idParent
1 null
2 1
3 null
4 null
5 4
Projects
id idParent
1 null
2 null
3 2
4 2
5 null
TeamProjects
idTeam idProject
2 2
3 1
5 5
项目总是依赖于至少一个团队,这就是teamprojects的用途。
我试图实现的结果:对于每个对象(团队和项目),我想知道什么是上升和后代对象(id连接)
idObject ascendantTeams descendantTeam ascendantProjects descendantProjects
1 2 7, 10
2 1 7
3 6
4
5 4 10
6 3
7 2 8, 9
8 2 7
9 2 7
10 5
我正在尝试使用linq to entity查询来实现这一点,但是我需要CTE(用于递归部分)和(stuff-for-xml)用于连接部分......并且都不能将linq转换为实体。 所以我试图提供帮助,但我也没有设法为它编写sql。
如何使用linq to entities或sql?
解决这个问题答案 0 :(得分:1)
你所拥有的不是很清楚。
所以,我做了一些假设,以便提出解决方案。我假设一个项目将包含在descendantProjects中,用于基于团队的结果(参见dbo.GetProjectsForTeam
),一个团队将被包含在descendantTeams中,用于基于项目的结果(参见dbo.GetTeamsForProject
)。从你的问题来看,这一点都不清楚。
您需要创建标量值函数来实现您的场景。
如何调用标量值函数
这些函数中的每一个都有两个参数 - 一个类型参数,对于后代来说是a
,对于后代来说是d
,而对于基于团队的查询,它将是团队ID的id基于项目的查询的项目ID 。
团队相关标量值函数
CREATE FUNCTION [dbo].[GetTeamsForTeam](
@teamType VARCHAR(20) , --either 'a' for ascendants or 'd' for descendants
@teamId INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @list VARCHAR(MAX);
IF @teamType = 'a'
BEGIN
--get all parent teams
SELECT @list = COALESCE(@list+','+CAST(t.Id AS VARCHAR(10)) , CAST(t.Id AS VARCHAR(10)))
FROM dbo.Teams AS t
WHERE t.Id IN ( SELECT t2.IdParent
FROM dbo.Teams AS t2
WHERE t2.id = @teamId
);
END;
ELSE
BEGIN
--get all children teams including @teamId
SELECT @list = COALESCE(@list+','+CAST(t.Id AS VARCHAR(10)) , CAST(t.Id AS VARCHAR(10)))
FROM dbo.Teams AS t
WHERE t.Id IN ( SELECT t2.Id
FROM dbo.Teams AS t2
WHERE t2.IdParent = @teamId
OR
t2.Id = @teamId
);
END;
RETURN @list;
END;
GO
CREATE FUNCTION [dbo].[GetProjectsForTeam](
@projectType VARCHAR(1) , --either 'a' for ascendants or 'd' for descendants
@teamId INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @projects VARCHAR(MAX);
IF @projectType = 'a'
BEGIN
--get projects for all the parents of @teamId
SELECT @projects = COALESCE(@projects+','+CAST(tp.idProject AS VARCHAR(10)) , CAST(tp.idProject AS VARCHAR(10)))
FROM dbo.TeamProjects AS tp
WHERE tp.idTeam IN ( SELECT t.IdParent
FROM dbo.Teams AS t
WHERE t.Id = @teamId
);
END;
ELSE
BEGIN
--get projects for all children of @teamId including @teamId
SELECT @projects = COALESCE(@projects+','+CAST(tp.idProject AS VARCHAR(10)) , CAST(tp.idProject AS VARCHAR(10)))
FROM dbo.TeamProjects AS tp
WHERE tp.idTeam IN ( SELECT t.Id
FROM dbo.Teams AS t
WHERE t.IdParent = @teamId OR t.Id = @teamId
);
END;
RETURN @projects;
END;
GO
使用上述标量值函数,基于团队的查询来实现最终结果集如下所示。
SELECT t.id AS TeamId,
dbo.GetTeamsForTeam('a', t.id) AS ascendantTeams,
dbo.GetTeamsForTeam('d', t.id) AS descendantTeams,
dbo.GetProjectsForTeam('a', t.id) AS ascendantProjects,
dbo.GetProjectsForTeam('d', t.id) AS descendantProjects
FROM Teams t;
与项目相关的标量值函数
CREATE FUNCTION [dbo].[GetTeamsForProject] (
@teamType VARCHAR(20) , --either 'a' for ascendants or 'd' for descendants
@projectId INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @list VARCHAR(MAX);
IF @teamType = 'a'
BEGIN
--get all parent teams
SELECT @list = COALESCE(@list+','+CAST(t.Id AS VARCHAR(10)) , CAST(t.Id AS VARCHAR(10)))
FROM dbo.Teams AS t
WHERE t.Id IN ( SELECT t2.IdParent
FROM dbo.Projects AS p INNER JOIN dbo.TeamProjects AS tp ON p.Id = tp.idProject
INNER JOIN dbo.Teams AS t2 ON t2.id = tp.idTeam
WHERE p.id = @projectId
);
END;
ELSE
BEGIN
--get all children teams including team for @projectId
SELECT @list = COALESCE(@list+','+CAST(t.Id AS VARCHAR(10)) , CAST(t.Id AS VARCHAR(10)))
FROM dbo.Teams AS t
WHERE t.Id IN ( SELECT t2.Id
FROM dbo.Projects AS p INNER JOIN dbo.TeamProjects AS tp ON p.Id = tp.idProject
INNER JOIN dbo.Teams AS t2 ON t2.id = tp.idTeam
WHERE p.IdParent = @projectId OR p.Id = @projectId
);
END;
RETURN @list;
END;
GO
CREATE FUNCTION [dbo].[GetProjectsForProject] (
@projectType VARCHAR(1) , --either 'a' for ascendants or 'd' for descendants
@projectId INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @projects VARCHAR(MAX);
IF @projectType = 'a'
BEGIN
--get projects for all the parents of @projectId
SELECT @projects = COALESCE(@projects+','+CAST(p.idParent AS VARCHAR(10)) , CAST(p.idParent AS VARCHAR(10)))
FROM dbo.Projects AS p
WHERE p.Id IN ( SELECT p.IdParent
FROM dbo.Projects AS p
WHERE p.Id = @projectId
);
END;
ELSE
BEGIN
--get projects for all children of @projectd
SELECT @projects = COALESCE(@projects+','+CAST(p.id AS VARCHAR(10)) , CAST(p.id AS VARCHAR(10)))
FROM dbo.Projects AS p
WHERE p.IdParent IN ( SELECT p.Id
FROM dbo.Projects AS p
WHERE p.IdParent = @projectId OR p.Id = @projectId
);
END;
RETURN @projects;
END;
GO
使用上述基于项目的函数,基于项目的查询的查询如下所示。
SELECT p.id AS ProjectId,
dbo.GetTeamsForProject('a', p.id) AS ascendantTeams,
dbo.GetTeamsForProject('d', p.id) AS descendantTeams,
dbo.GetProjectsForProject('a', p.id) AS ascendantProjects,
dbo.GetProjectsForProject('a', p.id) AS descendantProjects
FROM dbo.Projects p;
我使用的样本数据和最终查询的屏幕截图如下所示。