【问题标题】:How to LEFT JOIN 3 Tables Without Getting Duplication in MYSQL如何在 MYSQL 中 LEFT JOIN 3 个表而不出现重复
【发布时间】:2019-12-12 03:37:46
【问题描述】:

从用户中选择 *

USERID  NAME    STATUS
1       AAA     Supervisor
2       BBB     Member
3       CCC     Admin

从出席中选择 *

NO  DATE        SUPERVISOR  USERID  ADMIN
1   2019-12-07  1           2
2   2019-12-08  1           2
3   2019-12-09  1           2
4   2019-12-10  1           2
5   2019-12-11              1       CCC

从细节中选择 *

NO  USERID  ATTENDANCE  REASON
1   2       0           SICK
2   2       0           MEETING
3   2       0           NO REASON
4   2       0           SICK
5   1       0           MEETING

这是我尝试过的 SQL 和结果

选择 u1.userid, a.date, u1.name, d.reason, u2.name 作为主管, a.admin 作为管理员来自用户 u1 LEFT JOIN 出席 a ON u1.userid = a.userid LEFT JOIN user u2 ON a.supervisor = u2.userid LEFT JOIN detail d ON u1.userid = d.userid WHERE d.attendance = 0 SQLFiddle

USERID  DATE        NAME    REASON        SUPERVISOR    ADMIN
2       2019-12-07  BBB     SICK          AAA
2       2019-12-08  BBB     MEETING       AAA
2       2019-12-09  BBB     NO REASON     AAA
2       2019-12-10  BBB     SICK          AAA
2       2019-12-07  BBB     SICK          AAA
2       2019-12-08  BBB     MEETING       AAA
2       2019-12-09  BBB     NO REASON     AAA
2       2019-12-10  BBB     SICK          AAA
2       2019-12-07  BBB     SICK          AAA
2       2019-12-08  BBB     MEETING       AAA
2       2019-12-09  BBB     NO REASON     AAA
2       2019-12-10  BBB     SICK          AAA
2       2019-12-07  BBB     SICK          AAA
2       2019-12-08  BBB     MEETING       AAA
2       2019-12-09  BBB     NO REASON     AAA
2       2019-12-10  BBB     SICK          AAA
1       2019-12-11  AAA     MEETING       NULL          CCC

复制的工作方式如下: 如果attendancedetail(我不确定)表有4 个成员数据,它将循环4 次。如果是 5 个数据,那么 5 次等等..

我想要的结果:

USERID  DATE        NAME    REASON        SUPERVISOR    ADMIN
2       2019-12-07  BBB     SICK          AAA
2       2019-12-08  BBB     MEETING       AAA
2       2019-12-09  BBB     NO REASON     AAA
2       2019-12-10  BBB     SICK          AAA
1       2019-12-11  AAA     MEETING                     CCC

谢谢

【问题讨论】:

  • attendancedetail 之间没有链接来指示哪个detail 行属于哪个attendance 行。您需要添加一个链接两者的字段,以便可以在其上连接表格;这将防止您看到的重复。
  • 你必须修复你的表关系
  • @Nick 如果不添加新表就无法解决我的问题吗?
  • 我做了这个,看看这个:sqlfiddle.com/#!9/69dc1/2
  • 你的日期和原因没有关系

标签: mysql


【解决方案1】:

这是我们可以做的。

让我们根据NO 列为您的attendancedetails 表生成行号。我相信每次插入 1 detail 行对应于基于用户 ID 的每个 attendance 行。

SELECT u1.userid, a.date, u1.name, d.reason, u2.name as supervisor, a.admin as admin 
FROM user u1 
LEFT JOIN (
  SELECT 
      (@row_number:=@row_number + 1) AS num, 
      date,
      userid,
      admin,
      supervisor
  FROM
      attendance,
      (SELECT @row_number:=0) AS t
  ORDER BY 
      NO) a ON u1.userid = a.userid 
LEFT JOIN user u2 ON a.supervisor = u2.userid and u2.status='Supervisor'
LEFT JOIN 
  (SELECT 
      (@rn:=@rn + 1) AS num, 
      reason,
      userid,
      attendance
  FROM
      detail,
      (SELECT @rn:=0) AS t
  ORDER BY 
      NO ) d ON u1.userid = d.userid and d.num = a.num
where d.attendance = 0 

sqlfiddle

【讨论】:

  • 谢谢!尽管 sql 很长.. XD
【解决方案2】:

您在出勤和明细之间没有链接来指示哪个明细行属于哪个出勤行。您需要添加一个链接两者的字段,以便可以在其上连接表格;这将防止您看到的重复。解决此问题的一种方法是将DATE 列添加到detail。看到这个demo on SQLfiddle

SELECT u1.userid, a.date, u1.name, d.reason, u2.name as supervisor, a.admin as admin 
FROM user u1 
LEFT JOIN attendance a ON u1.userid = a.userid 
LEFT JOIN user u2 ON a.supervisor = u2.userid 
LEFT JOIN detail d ON u1.userid = d.userid AND d.date = a.date
WHERE d.attendance = 0

输出

userid  date        name    reason      supervisor  admin
2       2019-12-07  BBB     SICK        AAA     
2       2019-12-08  BBB     MEETING     AAA     
2       2019-12-09  BBB     NO REASON   AAA     
2       2019-12-10  BBB     SICK        AAA     
1       2019-12-11  AAA     MEETING     (null)      CCC

【讨论】:

    猜你喜欢
    • 2013-04-19
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多