MYSQL 加入子查询问题

MYSQL joining subquery issue

我有一个 table 里面有人们的成绩。

+---------+--------+--------+--------+---------------------+
|  name   | grade1 | grade2 | grade3 |      datetime       |
+---------+--------+--------+--------+---------------------+
| person1 |     50 |     80 |    100 | 2015-05-05 12:00:00 |
| person1 |     60 |     43 |     88 | 2015-05-05 12:00:00 |
| person1 |     11 |     80 |     44 | 2015-05-05 12:00:00 |
| person1 |     64 |     75 |     37 | 2015-05-05 12:00:00 |
| person1 |     83 |     34 |     99 | 2015-05-05 12:00:00 |
| person2 |     45 |    100 |     95 | 2015-05-05 12:00:00 |
| person2 |     76 |     75 |     54 | 2015-05-05 12:00:00 |
| person2 |     68 |     53 |     66 | 2015-05-05 12:00:00 |
| person2 |     45 |     12 |     85 | 2015-05-05 12:00:00 |
| person2 |     75 |     78 |     55 | 2015-05-05 12:00:00 |
+---------+--------+--------+--------+---------------------+

我需要做的是提取一个人在特定日期的成绩,然后提取一个字符串来表示他们 pass/fail 前(最多 7)天的报告。

我根据 table 寻找的最终结果将是这样的:

+---------------+---------+--------+--------+--------+----------------+
|    report     |  name   | grade1 | grade2 | grade3 |    datetime    |
+---------------+---------+--------+--------+--------+----------------+
| pass:3 fail:2 | person1 |     50 |     80 |    100 | 5/5/2015 12:00 |
| pass:2 fail:3 | person2 |     42 |    100 |     95 | 5/5/2015 12:00 |
+---------------+---------+--------+--------+--------+----------------+

所以我 sql 获得第一部分非常简单:

SELECT *
FROM Grades.grade_table gt
WHERE gt.datetime = '2015-05-05 12:00:00'

我的查询的第二部分如下所示:

SELECT CONCAT('fail:',SUM(CASE WHEN pass_fail = 'fail' THEN 1 ELSE 0 END),' pass:',SUM(CASE WHEN pass_fail = 'pass' THEN 1 ELSE 0 END)) trend_data
FROM (
    SELECT
    CASE
        WHEN ((grade1+grade2+grade3)/3) >= 65 THEN 'pass'
        ELSE 'fail'
    END AS pass_fail
    FROM Grades.grade_table gt
    WHERE gt.name = 'person1'
    LIMIT 7
) trend_data

我尝试过的:

SELECT 
(
  SELECT CONCAT('fail:',SUM(CASE WHEN pass_fail = 'fail' THEN 1 ELSE 0 END),' pass:',SUM(CASE WHEN pass_fail = 'pass' THEN 1 ELSE 0 END)) trend_data
  FROM (
    SELECT
    CASE
      WHEN ((grade1+grade2+grade3)/3) >= 65 THEN 'pass'
      ELSE 'fail'
    END AS pass_fail
    FROM Grades.grade_table gt
    WHERE gt.name = original_data.name
    LIMIT 7
  ) trend_data
) AS trending_data, original_data.*
FROM
(
  SELECT *
  FROM Grades.grade_table gt
  WHERE gt.datetime = '2015-05-05 12:00:00'
)

我一直无法在 where 子句中找到 original_data.name,但我认为它会通过,因为它在一个单独的 select 中,它是别名的。

我试图重建您的模式并创建一个简单的查询来满足您的需求。

SQLfiddle: http://sqlfiddle.com/#!9/74eb5e/61

获取成功与失败的查询:

SELECT name AS 'Name',
    CONCAT(
      'Fail: ',
      CAST(SUM(CASE WHEN (grade1+grade2+grade3)/3 <= 65 THEN 1 ELSE 0 END) AS CHAR(20)),
      ' Success: ',
      CAST(SUM(CASE WHEN (grade1+grade2+grade3)/3 > 65 THEN 1 ELSE 0 END) AS CHAR(20))) AS 'Report',
      NOW() AS 'Report date'
FROM grade_table gt1
WHERE (SELECT COUNT(*) 
       FROM grade_table
       WHERE name = gt1.name
       AND gradedate > gt1.gradedate
       ORDER BY gradedate ASC) < 7
GROUP BY name;

编辑 1:

新代码和更新的 SQLfiddle 满足您的要求(每个人的失败和成功的最后 7 天)。

编辑 2:

这基本上是一个更复杂的问题,此处有详细描述:

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

一般来说,您不能轻易地为此类子句使用 LIMIT,因为您想要限制每个组 (GROUP BY name)。但是,您可以使用类似这样的方法来获取每组的前 N ​​条记录:

SELECT name, gradedate
FROM grade_table gt1
WHERE (SELECT COUNT(*) 
       FROM grade_table
       WHERE name = gt1.name
       AND gradedate > gt1.gradedate
       ORDER BY gradedate ASC) < 2

它将检查组中的特定记录是否有 (COUNT(*)) 少于两条具有更大(更新)日期的记录。它只是意味着它只能是该记录,也可以是其中一个更大的记录。

我已经更新了最终解决方案,因此它现在应该可以满足您的需求。 请注意,提供的解决方案不是很有效,尽管它可以扩展为 N 个可能的名称。 我建议您阅读所提供的博客,因为文章下方有更多示例和一些很棒的评论,短时间内很难在这里详述。