MySQL中有多个多对多的关系

时间:2016-10-16 15:11:29

标签: mysql sql many-to-many left-join

对于我正在处理的项目,我正在尝试查询时钟,但是当我LEFT JOIN多次复用时(或者在单个用户中记录感,1到多次)它会创建重复的条目,因此当它按分组时,总计不正确。

鉴于以下模拟架构: enter image description here

一个查询:

SELECT
UserTbl.UserID,
CONCAT_WS(", ", UserTbl.LastName, UserTbl.FirstName) AS UserName,
SUM(TIMESTAMPDIFF(MINUTE,  TimeClockTbl.StartDateTime, TimeClockTbl.EndDateTime)) AS ClockedInMinutes,
FROM
Users AS UserTbl
LEFT JOIN
TimeClock AS TimeClockTbl
ON UserTbl.UserID = TimeClockTbl.UserID
LEFT JOIN
UserRoles AS UserRoleTbl
ON UserTbl.UserID = UserRoleTbl.UserID
WHERE
UserRoleTbl.RoleID IN (1,2,3)
GROUP BY
UserTbl.UserID
ORDER BY
UserTbl.LastName ASC,
UserTbl.FirstName ASC;

如果用户只有1个角色,则分配,它可以正常工作,但如果分配了第二个或第三个角色,它似乎会乘以最终结果。我考虑过使用GROUP_CONCAT作为角色并在之后进行过滤,但这似乎并不高效。我还考虑了子查询来计算给定用户的以小时为单位的时钟,但我觉得这会得到相同的结果。同样重要的是要注意,它被缩放为具有包含多个条目的TimeClock表,以及具有多个条目的Scheduled表。

如何才能以相当高的效率实现这一目标?

1 个答案:

答案 0 :(得分:1)

简单的决定:

SELECT UserTbl.UserID,
       CONCAT_WS(", ", UserTbl.LastName, UserTbl.FirstName) AS UserName,
       SUM(TIMESTAMPDIFF(MINUTE, TimeClockTbl.StartDateTime, TimeClockTbl.EndDateTime)) AS ClockedInMinutes,
  FROM Users AS UserTbl
  LEFT JOIN TimeClock AS TimeClockTbl ON UserTbl.UserID = TimeClockTbl.UserID
 WHERE UserTbl.UserID IN( SELECT UserID FROM UserRoles WHERE RoleID IN (1,2,3) )
 GROUP BY UserTbl.UserID
 ORDER BY UserTbl.LastName ASC, UserTbl.FirstName ASC;

类似情况的概念 - 一致联合:

SELECT A.*,
       SUM(TIMESTAMPDIFF(MINUTE, TimeClockTbl.StartDateTime, TimeClockTbl.EndDateTime)) AS ClockedInMinutes,
       MAX(A.RolesTitle) AS RolesTitle
  FROM (
        SELECT UserTbl.UserID,
               CONCAT_WS(", ", UserTbl.LastName, UserTbl.FirstName) AS UserName,
               FirstName, LastName,
               GROUP_CONCAT(Roles.Title) as RolesTitle
          FROM Users AS UserTbl
          JOIN UserRoles AS UserRoleTbl  ON UserTbl.UserID = UserRoleTbl.UserID
          JOIN Roles ON Roles.RoleID=UserRoleTbl.RoleID
         WHERE UserRoleTbl.RoleID IN (1,2,3)
         GROUP BY UserTbl.UserID
       ) A
  LEFT JOIN TimeClock AS TimeClockTbl ON A.UserID = TimeClockTbl.UserID
 GROUP BY A.UserID
 ORDER BY A.LastName ASC, A.FirstName ASC;