在两个表之间获取不同的记录(MySQL)

4
我需要展示“预定与实际”报告,该报告展示了持有学校出勤数据的MySQL数据库中两个表之间的差异。
我有两个称为Booking和Attendance的表。
表中存储的数据如下:
Booking表:
Id Student   Date     IsAbsent
1  John      20160216    1 //NO
2  Bob       20160217    1 //NO
3  Zara      20160218    1 //NO

出席记录。
Id Student    Date     IsAbsent
1  John       20160216    0 //YES
2  Bob        20160217    0 //YES
3  Mary       20160217    1 //NO

基本上,我想将输出显示为:

**Id | Student | Day_1 | Day_2  |  Day_3**
 ==== ========= ======  =======  ======
   1 | John    |ABSENT | NULL   | NULL 
   2 | Bob     |NULL   |ABSENT  | NULL
   3 | Mary    |NULL   |NEW     | NULL
   4 | Zara    |DELETED|NULL    | NULL

缺席 在预订表中,约翰被标记为1(假),但在出勤表中,他被标记为0(是),因此我想显示为“缺席”。

新增 玛丽仅在出勤表中有记录,但在预订表中没有记录。

已删除 萨拉最初被预订,并在预订表中,但不在出勤表中。

我已经创建了 SQL Fiddle 的模式和查询,但它总是返回空值。

我的 SQL 查询如下所示...

 SELECT * FROM 
((SELECT
  a.Student as student,
   MAX( case
       when a.DropDate='20160216' && a.IsAbsent=0 && s.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160216')=0 && (select count(*) from staging where DropDate='20160216')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160216')>0 && (select count(*) from staging where DropDate='20160216')=0 then 'New Booking' 
       else ' ' end ) as 'day_1',
  MAX( case 
       when a.DropDate='20160217' && a.IsAbsent=0 && s.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160217')=0 && (select count(*) from staging where DropDate='20160217')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160217')>0 && (select count(*) from staging where DropDate='20160217')=0 then 'New Booking' 
       else ' '  end ) as 'day_2',
  MAX( case 
       when a.DropDate='20160218' && a.IsAbsent=0 && s.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160218')=0 && (select count(*) from staging where DropDate='20160218')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160218')>0 && (select count(*) from staging where DropDate='20160218')=0 then 'DELETED Booking' 
       else ' '  end ) as 'day_3'
FROM Attendance a LEFT JOIN Booking s on a.Student=s.Student
WHERE a.DropDate IN ('20160216','20160217','20160218')
   AND  NOT EXISTS 
      ( SELECT 1
        FROM Booking AS p
        WHERE p.Student = a.Student
          AND p.IsAbsent = a.IsAbsent
          AND p.DropDate = a.DropDate
      )
)
UNION 
(SELECT
  t.Student as student,
  MAX( case
       when t.DropDate='20160216' && a.IsAbsent=0 && t.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160216')=0 && (select count(*) from staging where DropDate='20160216')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160216')>0 && (select count(*) from staging where DropDate='20160216')=0 then 'New Booking' 
       else ' ' end ) as 'day_1',
  MAX( case 
       when a.DropDate='20160217' && a.IsAbsent=0 && t.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160217')=0 && (select count(*) from staging where DropDate='20160217')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160217')>0 && (select count(*) from staging where DropDate='20160217')=0 then 'New Booking' 
       else ' '  end ) as 'day_2',
  MAX( case 
       when a.DropDate='20160218' && a.IsAbsent=0 && t.IsAbsent=1 then 'Absent'
       when (select count(*) from attendance where DropDate='20160218')=0 && (select count(*) from staging where DropDate='20160218')>0 then 'DELETED Booking'
       when (select count(*) from attendance where DropDate='20160218')>0 && (select count(*) from staging where DropDate='20160218')=0 then 'DELETED Booking' 
       else ' '  end ) as 'day_3'
FROM Booking t LEFT JOIN attendance a on t.Student=a.Student
WHERE t.DropDate IN ('20160216','20160217','20160218')
  AND  NOT EXISTS 
      ( SELECT 1
        FROM Attendance AS u
        WHERE u.Student = t.Student
          AND u.IsAbsent = t.IsAbsent
          AND u.DropDate = t.DropDate
      )
)) tbl
ORDER BY  student

任何帮助都将不胜感激。

这很有趣。我正在管道中有一个类似的问题,正在跟进这个。 - chapskev
1个回答

2

我不确定你是否能在MySQL查询中输出内联布局,除非你使用存储过程...我不知道这对你是否可行,因为它的布局略有不同,但它可以工作:

(select s.Student,
       s.ClassRoom,
       s.DropDate,
       if(s.IsAbsent=1&&a.IsAbsent=0,'ABSENT','PRESENT')
from Staging s inner join Attendance a on a.Student = s.Student and a.ClassRoom = s.ClassRoom and a.DropDate = s.DropDate)
UNION ALL
(Select s.Student,
       s.ClassRoom,
       s.DropDate,
       'DELETED'
from Staging s left join Attendance a on a.Student = s.Student and a.ClassRoom = s.ClassRoom and a.DropDate = s.DropDate
where a.Student is null)
UNION ALL
(Select a.Student,
       a.ClassRoom,
       a.DropDate,
       'NEW'
from Staging s right join Attendance a on a.Student = s.Student and a.ClassRoom = s.ClassRoom and a.DropDate = s.DropDate
where s.Student is null)
order by Student, DropDate;

谢谢@Stan,这正是我想要实现的结果,但我需要将日期横向显示 :-( - snowflakes74
动态透视似乎很合适。我找到了一篇有趣的教程:http://buysql.com/mysql/14-how-to-automate-pivot-tables.html - St3an
谢谢,我最终使用了您的查询,并将结果集插入到一个临时表中,然后对其进行动态透视。由于这只是一次性的操作,所以我已经硬编码了日期,但在实际情况下可能需要不同的逻辑处理: - snowflakes74
创建临时表AttendanceDiff( 学生 int(5) NOT NULL, 教室 int(5) NOT NULL, 掉落日期 varchar(12)NOT NULL, 状态 varchar (12) )SELECT 学生, case(掉落日期) when '20160222' then CONCAT(状态) else ' ' end as 'day_1', case(掉落日期) when '20160223' then CONCAT(状态) else ' ' end as 'day_2' FROM AttendanceDiffDROP TABLE AttendanceDiff - snowflakes74

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接