Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2376167
  • 博文数量: 609
  • 博客积分: 10061
  • 博客等级: 上将
  • 技术积分: 5920
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-25 08:30
文章分类

全部博文(609)

文章存档

2010年(13)

2009年(39)

2008年(558)

我的朋友

分类: Mysql/postgreSQL

2008-09-01 10:50:07

Mysql入门系列:MySQL教程(11)



   此查询找出具有给定日期的记录,然后利用该记录中的事件ID 查找具有相同事件ID 的学分。对于每个匹配的事件记录和学分记录组合,显示学生ID、学分、日期和事件类型。此查询在两个重要方面不同于我们曾经编写过的其他查询。它们是:

  ■ FROM 子句给出了不止一个表名,因为我们要检索的数据来自不止一个表:

  FROM event,score

  ■ WHERE 子句说明event 和score 表是由每个表中的event_id 值的匹配连接起来的:

  where event.event_id=score.event_id

  请注意,我们是怎样利用tbl_name.col_name 语法引用列,以便MySQL知道引用的是哪些表的列。(event_id 出现在两个表中,如果不用表名来限定它的话将会出现混淆。)此查询中的其他列( date、score、type)可单独使用而不用表名限定符,因为它们在表中只出现一次,从而不会出现含混。但是,一般在连接中我们对每个列都进行限定以便清晰地表示出每个列是属于哪个表。在完全限定的形式下,查询如下:


  从现在起,我们将使用完全限定的形式。第二步,我们利用student 表完成查询以便显示学生名。(第一步中查询的输出给出了student_id 字段,但是名字更有意义。)名字显示是利用score 表和student 表两者都具有student_id 列,使它们中的记录可被连接这个事实来完成的。最终的查询如下:


  此查询与前一个查询的差别在于:

  ■ student 表被增加到了FROM 子句中,因为除了event 表和score 表外还用到了它。

  ■ student_id 列现在不明确了(因为现在有两个引用到的表都含有此列),因此必须限定为score.student_id 或student.student_id 以表明使用的是哪个表。

  ■ WHERE 子句有一个附加项,它说明根据学生ID 将score 表记录与student 表记录进行匹配。

 ■ 此查询是显示学生名而不是学生ID。(当然,如果愿意的话,可以两者都显示。)利用此查询,可以加入任意日期,得到该日期的学分,用学生名和学分类型完善查询结果。不一定要了解关于学生ID 或事件ID 的情况。MySQL小心地得出相关的ID 值并利用它们自动地使各表的行相配。

 学分保存方案涉及的另一项工作是汇总学生的缺勤情况。缺勤情况是按学生ID 和日期在absence 表中记录的。为得到学生名(而不仅仅是ID),我们需要根据student_id 的值将absence 表连接到student 表。下面的查询给出了学生的ID 号和名字以及缺勤计数:


    注意:虽然我们在GROUP BY 子句中应用了一个限定符,但对于这个查询来说不是必须的。因为GROUP BY 子句只引用选择表中(此查询的前两行)的列。在该处只有一个名为student_id 的列,因此MySQL知道应该用哪个列。这个规则对ORDER BY 子句也成立。如果我们希望只了解哪些学生缺过勤,则此查询所产生的输出也是有用的。但是,如果我们将此清单交给学校办公室,他们可能会说,“其他的学生呢?我们需要每个学生的情况。”这是一个稍微有点不同的问题。它表示需要知道学生的缺勤数,即使没有缺勤的学生也需要知道。因为问题的不同,查询也应该不同。

   为了解决上述问题,使用LEFT JOIN 而不涉及WHERE 子句中的学生ID。LEFT JOIN要求MySQL对从连接首先给出的表中选择每行生成一个输出行(即LEFT JOIN 关键字左边给出的表)。由于首先给出student 表,我们得到了每个学生的输出结果,即使是那些在absence 表中未给出的学生也都包括在输出中。此查询如下:


   前面,在“生成汇总”一节中,我们执行了一个查询,它生成score 表中数据的数值特征。该查询的输出列出了事件ID,但不包括学分日期或类型,因为我们不知道怎样将score 表连接到event 表以得到学分的日期和类型。现在可以做到了。下面的查询类似于早先的那个,但是它给出了学分的日期和类型而不只是简单的数字事件ID:


  可利用诸如COUNT( ) 和AVG( ) 这样的函数生成多个列上的汇总,即使这些列来自不同的表也是如此。下面的查询确定学分数,以及事件日期与学生性别的每种组合的平均学分。


  我们可以使用一个类似的查询来完成学分保存方案的一个任务,即在学期末计算每个学生的总学分。相应的查询如下:


  不一定要求连接必须用两个不同的表来完成。这似乎有点奇怪,但是确实可以将一个表连接到其自身。例如,可通过针对每个总统的出生地查看其他各个总统的出生地,确定几个总统是否出生在相同城市。此查询如下:


  此查询有两个技巧性的东西:

   ■ 我们需要使用同一表的两个实例,因此建立了表的别名( p 1、p 2),并利用它们无歧义地引用表列。

   ■ 每个总统的记录与自身相匹配,但是我们不希望在输出中看到同一总统出再现两次。WHERE 子句的第二行保证比较的记录为不同总统的记录,使记录不与自身匹配。可以编写一个查找出生在同一天的总统的类似查询。出生日期不能直接比较,因为那样会错 过出生在不同年份的总统。我们用MONTH( ) 和DAYOFMONTH( ) 来比较出生日期的月和日,相应的查询如下:



  利用DAYOFYEAR( ) 而不是MONTH( ) 和DAYOFMONTH( ) 将得出一个更为简单的查询,但是在比较闰年日期与非闰年日期时将会得出不正确的结果。迄今所执行的连接结合了来自那些在某种意义上具有逻辑关系的表中的信 息,但是只有您知道该关系无意义。MySQL并不知道(或不关心)所连接的表相互之间是否相关。例如,可将event 表连接到president 表以找出在某个总统生日那天是否进行了测验或测试,此查询如下:


  它产生了您所想要的东西。但说明了什么呢?这说明MySQL将愉快地制造出结果,至于这些结果是否有意义它不管。这是因为您使用的是计算机,所以它不能自动地判断查询的结果有用或无用。无论如何,我们都必须为自己所做的事负责。
阅读(941) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~