SQL Server-CTE递归,在子';谁的数据?
这个问题延续了上一个已解决的问题(非常感谢弗拉基米尔·巴拉诺夫),可在此处访问: 数据结构与以前几乎相同,只是在EmOvertime中有另一个名为“AttdDate”的列来指示员工的出勤日期。下面是EmOvertime表中的数据示例SQL Server-CTE递归,在子';谁的数据?,sql,sql-server,Sql,Sql Server,这个问题延续了上一个已解决的问题(非常感谢弗拉基米尔·巴拉诺夫),可在此处访问: 数据结构与以前几乎相同,只是在EmOvertime中有另一个名为“AttdDate”的列来指示员工的出勤日期。下面是EmOvertime表中的数据示例 Table Name : EmOvertime EmpId AttdDate TotalOtReal 2 2016-05-09 2.00 2 2016-05-10 2.00
Table Name : EmOvertime
EmpId AttdDate TotalOtReal
2 2016-05-09 2.00
2 2016-05-10 2.00
2 2016-05-11 2.00
2 2016-05-12 2.00
3 2016-05-12 3.00
来自CsOrganization和EmHisOrganization的数据与前面的问题相同。假设我想在2016年5月12日显示所有组织数据及其TotalHours值,查询如下:
WITH
CTE_OrgHours
AS
(
SELECT
Org.OrgId
,Org.OrgParentId
,Org.OrgName
,ISNULL(Overtime.TotalOtReal, 0) AS SumHours
,Overtime.AttdDate
FROM
CsOrganization AS Org
LEFT JOIN EmHisOrganization AS Emp ON Emp.OrgId = Org.OrgID
LEFT JOIN EmOvertime AS Overtime ON Overtime.EmpId = Emp.EmpId
GROUP BY
Org.OrgId
,Org.OrgParentId
,Org.OrgName
,Overtime.TotalOtReal
,Overtime.AttdDate
)
,CTE_Recursive
AS
(
SELECT
CTE_OrgHours.OrgId
,CTE_OrgHours.OrgParentId
,CTE_OrgHours.OrgName
,CTE_OrgHours.SumHours
,CTE_OrgHours.AttdDate
,1 AS Lvl
,CTE_OrgHours.OrgId AS StartOrgId
,CTE_OrgHours.OrgName AS StartOrgName
FROM CTE_OrgHours
UNION ALL
SELECT
CTE_OrgHours.OrgId
,CTE_OrgHours.OrgParentId
,CTE_OrgHours.OrgName
,CTE_OrgHours.SumHours
,CTE_OrgHours.AttdDate
,CTE_Recursive.Lvl + 1 AS Lvl
,CTE_Recursive.StartOrgId
,CTE_Recursive.StartOrgName
FROM
CTE_OrgHours
INNER JOIN CTE_Recursive ON CTE_Recursive.OrgId = CTE_OrgHours.OrgParentId
)
SELECT
StartOrgId
,StartOrgName
,SUM(SumHours) AS TotalHours
FROM CTE_Recursive
WHERE AttdDate = '2016-05-12'
GROUP BY
StartOrgId
,StartOrgName
ORDER BY StartOrgId
但查询结果如下所示:
OrgId OrgName TotalHours
1 X COMPANY 14.00
2 Administrator 14.00
3 Adm 1 12.00
4 Adm 2 0.00
5 Adm 1_1 0.00
Desired Output
OrgId OrgName TotalHours
1 X COMPANY 5.00
2 Administrator 5.00
3 Adm 1 3.00
4 Adm 2 0.00
5 Adm 1_1 0.00
而正确的答案应该是这样的:
OrgId OrgName TotalHours
1 X COMPANY 14.00
2 Administrator 14.00
3 Adm 1 12.00
4 Adm 2 0.00
5 Adm 1_1 0.00
Desired Output
OrgId OrgName TotalHours
1 X COMPANY 5.00
2 Administrator 5.00
3 Adm 1 3.00
4 Adm 2 0.00
5 Adm 1_1 0.00
在EmOvertime中,孩子的数据似乎是作为其父数据的数量循环的,它有4个相同的ID。因此,显示值12.00。如何解决这个问题
任何帮助都将不胜感激。如果您对某个特定日期感兴趣,这很简单 看起来您需要将
WHERE
过滤器移动到查询的前面部分。进入CTE\u OrgHours
CTE_OrgHours
应为每个组织返回一行相关小时的总和。所有筛选都应在此查询中进行。递归部分稍后希望在CTE\u orghurs
中每个组织有一行
WITH
CTE_OrgHours
AS
(
SELECT
Org.OrgId
,Org.OrgParentId
,Org.OrgName
,ISNULL(SUM(Overtime.TotalOtReal), 0) AS SumHours
FROM
CsOrganization AS Org
LEFT JOIN EmHisOrganization AS Emp ON Emp.OrgId = Org.OrgID
LEFT JOIN EmOvertime AS Overtime
ON Overtime.EmpId = Emp.EmpId
AND Overtime.AttdDate = '2016-05-12'
GROUP BY
Org.OrgId
,Org.OrgParentId
,Org.OrgName
)
,CTE_Recursive
AS
(
SELECT
CTE_OrgHours.OrgId
,CTE_OrgHours.OrgParentId
,CTE_OrgHours.OrgName
,CTE_OrgHours.SumHours
,1 AS Lvl
,CTE_OrgHours.OrgId AS StartOrgId
,CTE_OrgHours.OrgName AS StartOrgName
FROM CTE_OrgHours
UNION ALL
SELECT
CTE_OrgHours.OrgId
,CTE_OrgHours.OrgParentId
,CTE_OrgHours.OrgName
,CTE_OrgHours.SumHours
,CTE_Recursive.Lvl + 1 AS Lvl
,CTE_Recursive.StartOrgId
,CTE_Recursive.StartOrgName
FROM
CTE_OrgHours
INNER JOIN CTE_Recursive ON CTE_Recursive.OrgId = CTE_OrgHours.OrgParentId
)
SELECT
StartOrgId
,StartOrgName
,SUM(SumHours) AS TotalHours
FROM CTE_Recursive
GROUP BY
StartOrgId
,StartOrgName
ORDER BY StartOrgId;
我之前的尝试确实是试图将WHERE子句从最终SELECT移到CTE_orghurs中,但没有成功。但后来我没有意识到,只有在ON子句中添加“AND加班。AttdDate='2016-05-12'”才起作用。再次感谢你,你真的帮了我大忙。将此标记为答案!