我想查询数据库中的用户以及他们在每个活动类别上花费的时间。这些类别存储在表ActivityCategory(int Id,varchar Name)中。其中只有8个,我希望看到所有这些,即使没人花时间在特定类别上。
我有以下查询:
select u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
from Users u
join Semaines s on u.EntityGuid=s.UserGuid
join HeuresProjets hp on s.Id=hp.WeekId
join Heures h on hp.HPId=h.HpGuid
join ActivityCodes code on h.Code=code.ActivityId
join ActivityCategory ac on code.Categorie=ac.Id
group by u.NoEmploye, u.FirstName, u.LastName, ac.Name
order by u.NoEmploye
它工作正常,但它不会返回未使用的ActivityCategories。我尝试了full / left / right / inner / outer / you-name-it join的每个组合。当没有人使用类别时,我能得到的最好的是完全空行,而对于特定用户不使用但其他人不使用的类别,我将获得null ac.Name。我怀疑group by [...]
ac.Name
部分正在“吃掉”未使用的类别。我究竟做错了什么?我应该编写第二个选择查询来对结果进行分组吗?我还有十几个类似的查询要写,所以我想了解而不仅仅是有一个没有解释的固定查询。
修改 Lamak的第二个查询到目前为止工作,但是当我添加where子句时它也有同样的问题。
EDIT2 ypercube'编辑效果很好
现在让我们看看我是否正确理解了查询。 当结果为null时,我将Sum与0合并以具有proprer值。我从ActivityCategory开始选择,以确保我拥有所有这些,甚至是未使用的,我与用户交叉加入,以拥有ActivityCategory和Users的每个组合。我离开加入Activitycodes只获取相关的行,然后我内部加入我的其他表来到Semaine。我的条件应用于Semaine表的连接,因为我想在交叉连接之前过滤我的数据。最后,我按用户和ActivityCategory对数据进行分组以使总和有效。
答案 0 :(得分:4)
这应该做:
SELECT u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
FROM ActivityCategory ac
LEFT JOIN ActivityCodes code
ON code.Categorie=ac.Id
LEFT JOIN Heures h
ON h.Code=code.ActivityId
LEFT JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
LEFT JOIN Semaines s
ON s.Id=hp.WeekId
LEFT JOIN Users u
ON u.EntityGuid=s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye
基本上,如果您想要所有类别,则需要将该表用作FROM
上的第一个表格并对该表格执行LEFT JOIN
。
<强>更新强>
如果您希望结果中的每个用户都使用每个类别,则需要CROSS JOIN
:
SELECT u.NoEmploye, u.FirstName, u.LastName, Total=sum(h.NbHeures), ac.Name
FROM ActivityCategory ac
CROSS JOIN Users u
LEFT JOIN ActivityCodes code
ON code.Categorie=ac.Id
LEFT JOIN Heures h
ON h.Code=code.ActivityId
LEFT JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
LEFT JOIN Semaines s
ON s.Id=hp.WeekId AND u.EntityGuid=s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye
要在添加WHERE
子句时解决此问题:
SELECT u.NoEmploye, u.FirstName, u.LastName,
Total=COALESCE(SUM(h.NbHeures),0), ac.Name
FROM ActivityCategory ac
CROSS JOIN Users u
LEFT JOIN
ActivityCodes code
JOIN Heures h
ON h.Code=code.ActivityId
JOIN HeuresProjets hp
ON hp.HPId=h.HpGuid
JOIN Semaines s
ON s.Id=hp.WeekId
AND (some condition on the dates) -- add here
ON ac.Id = code.Categorie
AND u.EntityGuid = s.UserGuid
GROUP BY u.NoEmploye, u.FirstName, u.LastName, ac.Name
ORDER BY u.NoEmploye