如何从使用UNION的表联接中获取MAX日期?

时间:2018-12-28 08:20:51

标签: mysql join union-all

我有3个表需要联接以获得最大日期。

table_grade_A
ID_GRADE    GRADE      NOTE    SURVEYOR
       1     70.7      PASS         TOM
       3     51.2      FAIL         TOM

table_grade_B
ID_GRADE    SUB_GRADE_I   SUB_GRADE_II   TOTAL_GRADE     NOTE    SURVEYOR
       2           30.8           40.1          70.9     PASS     MARVOLO
       4           10.3           54.1          64.4     FAIL     MARVOLO                       
       5           41.7           20.9          62.6     FAIL      RIDDLE 

table_grade
ID_GRADE    STUDENT       TEST_DATE
       1       MIYA      2018-12-20   
       2      LAYLA      2018-12-21
       3       MIYA      2018-12-21
       4       MIYA      2018-12-22
       5     KARRIE      2018-12-28

每个学生可能会得到不同的测试,并且不同的测试存储在不同的表中。我使用UNIONtable_grade_atable_grade_b填充值,然后将它们加入table_grade

我当前的查询:

SELECT tg.STUDENT, MAX(tg.TEST_DATE) AS 'TEST_DATE', temp_grade.* FROM `table_grade` tg 
INNER JOIN (
   SELECT ID_GRADE,GRADE,NOTE
   FROM table_grade_a 'tga'
   UNION ALL 
   SELECT ID_GRADE,TOTAL_GRADE AS GRADE,NOTE 
   FROM table_grade_a 'tgb'
)temp_grade ON tg.ID_GRADE = temp_grade.ID_GRADE 

WHERE tg.STUDENT = 'MIYA'

上述查询的结果是:

STUDENT    TEST_DATE    GRADE    NOTE
  MIYA    2018-12-22     70.7    PASS

预期输出应为:

STUDENT    TEST_DATE    GRADE    NOTE
  MIYA    2018-12-22     64.4    FAIL

2 个答案:

答案 0 :(得分:2)

对于每个学生的最大日期对应的结果:

一列的MIN或MAX不一定与所需行的其他值对齐,因此您需要做的不仅仅是计算最大日期。在版本8之前的MySQL中,您可以执行以下操作:计算最大日期,然后将其用作内部联接,以将行限制为与最大值对应的行:

select
    temp_grade .*
from table_grade tg
inner join (
    select student, max(test_date) as test_date
    from table_grade
    group by student
    ) gd on tg.student = gd.student and tg.test_date = gd.test_date
INNER JOIN (
   SELECT ID_GRADE,GRADE,NOTE
   FROM table_grade_a 'tga'
   UNION ALL 
   SELECT ID_GRADE,TOTAL_GRADE AS GRADE,NOTE 
   FROM table_grade_a 'tgb'
   )temp_grade ON tg.ID_GRADE = temp_grade.ID_GRADE 
# WHERE tg.STUDENT = 'MIYA'

在MySQL v8 +中,您可以改为使用row_number() over(...)

select
      temp_grade .*
from (
    select *
    , row_number() over(partition by student order by test_date DESC) as rn
    from table_grade
    )  tg
INNER JOIN (
   SELECT ID_GRADE,GRADE,NOTE
   FROM table_grade_a 'tga'
   UNION ALL 
   SELECT ID_GRADE,TOTAL_GRADE AS GRADE,NOTE 
   FROM table_grade_a 'tgb'
   )temp_grade ON tg.ID_GRADE = temp_grade.ID_GRADE 
where tg.rn = 1
# and tg.STUDENT = 'MIYA'

答案 1 :(得分:1)

当前方法的问题在于,您正在选择最大日期(表级聚合),同时还要求所有单个记录。这确实有道理。一种正确的可能性是将LIMITORDER BY一起使用:

SELECT tg1.STUDENT, tg1.TEST_DATE, tg2.*
FROM table_grade tg1
INNER JOIN
(
    SELECT ID_GRADE, GRADE, NOTE
    FROM table_grade_a
    UNION ALL 
    SELECT ID_GRADE, TOTAL_GRADE, NOTE 
    FROM table_grade_b
) tg2
    ON tg1.ID_GRADE = tg2.ID_GRADE 
WHERE
    tg1.STUDENT = 'MIYA'
ORDER BY
    tg1.TEST_DATE DESC
LIMIT 1;