因为Group By Statement而在mysql查询中有些奇怪

时间:2013-11-22 02:17:27

标签: php mysql sql

我有这张表记录用户的考试结果:

CREATE TABLE IF NOT EXISTS `ts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,
  `xid` int(11) NOT NULL,
  `lid` int(11) NOT NULL,
  `grade` double NOT NULL,
  `duration` varchar(10) COLLATE utf8_turkish_ci NOT NULL,
  `trues` int(11) NOT NULL DEFAULT '0',
  `falses` int(11) NOT NULL DEFAULT '0',
  `empties` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `uid` (`uid`),
  KEY `xid` (`xid`),
  KEY `lid` (`lid`),
) ENGINE=InnoDB;

我在表中记录了这些记录:

|id|uid|xid|lid|grade|duration|trues|falses|empties|    
+--+---+---+---+-----+--------+-----+------+-------+ 
|45| 20|  1|  1|   80|00:01:12|    8|     2|      0|
|46| 20|  1|  2|   40|00:02:31|    4|     6|      0|
|47| 20|  3|  1|  100|00:01:10|    1|     0|      0|
|48| 20|  4|  1|   83|00:00:51|    5|     1|      0|
|49| 20|  2|  1|    0|00:00:02|    0|     1|      0|
|53| 20|  4|  2|   50|00:00:04|    1|     1|      0|
|54| 20|  1|  2|   50|00:00:41|    5|     5|      0|

lid表示由xid表示的考试难度级别。我希望以独特的水平为每个独特的考试展示最高分。例如,有7行。 id [46]和id [54]用于相同的考试和水平。所以我必须在这两行中列出更高等级的值。

我提出了一个问题:

SELECT 
      failed.fgrade, 
      succeeded.sgrade, 
      ts.xid, 
      ts.lid, 
      ts.trues, 
      ts.falses, 
      ts.empties,  
      MAX(`grade`) AS grade, 
      ts.duration, 
      x.exam 
FROM 
      ts
JOIN 
      x ON ts.xid = x.id
JOIN 
      (SELECT 
             COUNT(DISTINCT(xid))  AS sgrade 
       FROM ts 
       WHERE uid = 20 AND grade >= 70) AS succeeded

JOIN 
      (SELECT 
             COUNT(DISTINCT(xid)) AS fgrade 
       FROM ts 
       WHERE uid = 20 AND grade < 70 ) AS failed

WHERE 
       ts.uid = 20

GROUP BY 
      xid, 
      lid
ORDER BY 
      ts.id

当我运行查询时,我得到了奇怪的结果:

Exam Name  Level    Duration     True   False   Empty    Total Grade  fgrade sgrade
Functions      1    00:00:02        0       1       0        1     0       3      3 
Numbers        2    00:02:31        4       6       0       10    50       3      3 (!) 
Equations      2    00:00:04        1       1       0        2    50       3      3 
Numbers        1    00:01:12        8       2       0       10    80       3      3 
Equations      1    00:00:51        5       1       0        6    83       3      3
Functions      1    00:01:10        1       0       0        1   100       3      3

如果你看一下结果表中的(!)行,就会有一些奇怪的东西。 4个正确答案和6个错误答案得到40分。但它显示了另一行的等级值,同时显示了自己的真假答案计数。

我基本上希望为给定的用户ID(uid)显示每个难度级别的所有不同考试。现在,当我写这个问题时,我开始认为这可能是由GROUP BY声明引起的。但是写这个问题还需要一段时间。我不能删除它。

1 个答案:

答案 0 :(得分:1)

请考虑以下两行:

|46| 20|  1|  2|   40|00:02:31|    4|     6|      0|
|54| 20|  1|  2|   50|00:00:41|    5|     5|      0|   

当按xid分组时,只选择一行(第一行)

|46| 20|  1|  2|   40|00:02:31|    4|     6|      0|

但是对于max(等级),它是一个聚合函数,它意味着它将查找get max value的所有结果行 - &gt;最高(等级)返回50.
- &gt;如果您在选择中添加成绩和最高(成绩),您将获得40和50。

在你的情况下,我认为你应该加入两个ts表,以获得更高的等级价值:

select ts1.* from ts ts1 left join ts laster on ts1.xid = laster.xid and ts1.lid = laster.lid
and ts1.uid = laster.uid and ts1.grade < laster.grade where isnull(laster.grade)