MYSQL加入子查询问题

时间:2015-05-05 18:57:32

标签: mysql sql join subquery

我有一张桌子里有人的成绩。

+---------+--------+--------+--------+---------------------+
|  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 |
+---------+--------+--------+--------+---------------------+

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

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

+---------------+---------+--------+--------+--------+----------------+
|    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,但我认为这会在一个单独的选择中出现,因为它是别名。

1 个答案:

答案 0 :(得分:1)

我尝试重建您的架构并创建一个简单的查询,告诉您需要什么。

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

查询获得成功和失败:

GROUP BY name

修改1:

新代码和更新后的SQLfiddle符合您的要求(每个人失败和成功的最后七天)。

编辑2:

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

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

一般情况下,您可以轻松使用此类子句的LIMIT,因为您希望限制每组(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 )。但是,你可以使用这样的东西来获得每组的前N个记录:

COUNT(*)

它将检查组中的特定记录是否(#navbar-image-ID2Games { width: 5rem; height: 5rem; background-repeat: no-repeat; background: url(http://i.imgur.com/Ou5cX4D.png); background-size: contain; } #navbar-image-ID2Games:hover { width: 5rem; height: 5rem; background: url(http://i.imgur.com/Tx0SVZr.png) no-repeat; background-size: contain; } )少于两个具有更大(更新)日期的记录。它只是意味着它只能是那个记录,也可以是一个更大的记录。

我已更新最终解决方案,因此它现在可以满足您的需求。 请注意,提供的解决方案效率不高,尽管它可以扩展名称的N种可能性。 我建议你阅读所提供的博客,因为这里有更多的例子和一些很好的评论,这些文章很难在短时间内详细阐述。