由于 Extract 是一个带函数的 表达式,为此其必须出现在 Group By 子句中。而且注意,笔者此时采用的是表达式本身, 而不是其别名。也就是说,笔者没有采用 group by 年度,月份等表达方法。也就是说,在 Group By 子句中,必须采用表达式的全称,而不能够采用其别名。否则的话,数据库系统 不会接受这个语句。数据库系统之所有要进行类似的控制,其背后藏有比较深层次的原因。 不过作为普通数据库管理员来说, 不怎么用了解数据库设计背后的内容。 只需要把这个规则 记在心中即可。这个规则对于大部分数据库管理员来说,可能会经常触犯他。为此笔者再次 强调一遍,选择列表中如果包含有列、表达式时,这个列、表达式必须包含在 Group By 子 句中。另外,如果采用了表达式的话,则数据库管理员即使在选择列表中采用了别名,但是 在 Group By 子句中仍然必须采用表达式的完整表达方式,而不能够采用别名。 如果在一个查询语句中,同时含有 Group By(分组语句)、Having(分组语句下的条件函 数)、Order By(排序语句)三个共存的话,则需要注意他们有一定的书写顺序。通常情况下 Order By 排序语句必须放置在最后。 如上面的案例中, 笔者就把这个排序语句放在最末尾的 地方。如果不这么处理的话,系统编译器是不会接受这个 PL/SQL 语句的。另外需要注意的 是,采用 Group 语句会自动对纪录进行排序。如上面的语句中,笔者并没有对年份、月度 进行排序,而只是按供应商名称来进行排序。而现实结果的话,却会自动按年度、月份的大 小从小到大来进行排序。这主要因为 Group By 子句在统计之前,会先对记录按照 Group By 中的参数从左到右来进行排序,然后再进行统计。如此的话,最后显示的结果就是已经排过 序来的结果。如果数据库管理员对于这个排序结果不满意的话,就需要通过 Order By 子句 再来对显示结果进行排序。 不过这里需要注意的是, 本身分组等子句就需要对纪录进行排序 并进行一定的业务逻辑处理,此时会耗费比较多的数据库资源。为此从数据库的性能考虑, 在使用 Order By 排序子句对统计结果进行重新排序的时候,要慎重。如果想把某个字段当 作第一顺序排序的话, 则只需要把这个字段放置在分组语句中的第一个参数即可。 如在上面 这 个 案 例 中 , 笔 者 完 全 可 以 通 过 group by p.name,extract(YEAR FROM t.dateordered),extract(MONTH FROM t.dateordered)这个分组语句来实现结果的排序,而可以 不再使用 Order By 语句。为此只有在必要的情况下,才能够利用 Order By 子句。 Group By 子句与 Where 子句是不兼容的。也就是说,在普通的 Select 等语句中(不含有 Group By 子句)时可以利用 Where 子句来过滤显示的结果。但是在上面的语句中,笔者却是 使用 Having 语句来过滤显示结果的。这主要是因为 Group By 子句与 Where 子句是不兼容 的。也就是说,当要显示分组显示结果时,数据库管理员必须要使用 Having 子句,而不能 够在 Where 自居中使用分组函数限制分组显示结果。如果数据库管理员在这里触犯这条原 则话,那么数据库系统就会拒绝接受这条语句。数据库会提示错误信息,如“命令没有正确 结束”等等。另外 Having 语句主要用来限制分组统计结果,其跟 Group By 语句是双胞胎。 即 Having 子句必须跟在 Group By 语句后面使用。其中 Group By 子句用户对查询结果进行 分组统计,而 Having 子句则用于限制分组显示结果,即根据用户的要求来部分显示所需要 的内容。 他们是互相配合, 分工合作。 可以说, 如果没有 Having 语句的帮助, 那么 Group By 语句会失色很多。另外,Having 语句对于提高数据库与应用服务器的性能也有很大的关系。 由于采用了 Having 语句来过滤显示的结果,那么其最终符合条件的结果肯定比没有设置限 制条件的要少的多。这也就意味着这个显示结果可以减少数据在网络中的传输,最好配上 Having 条件过滤语句(虽然这并不属于强制限制)。 如在在 ERP 系统中生成这张报表的时候, 可以提示用户输入参数, 如需要统计几几年几月份到几几年几月份的采购金额。 如果用户没 有输入相关的数据的话,则其默认为最近一年的统计数据等等。这虽然是一个小小的技巧, 但是在数据量比较多或者数据分组涉及到多张表的情况下, 可以非常有效的提高数据库与应 用服务器的性能。这是一个强制的条件,数据库管理员必须无条件的遵守。 需 要 注 意 多 列 分 组 的 顺 序 问 题 。 group by p.name,extract(YEAR FROM t.dateordered),extract(MONTH FROM t.dateordered 与 group by extract(YEAR FROM t.dateordered),extract(MONTH FROM t.dateordered ,p.name 这两个分组语句有什么差别吗?如 果光从结果上来说,是没有多大差异的。但是从其内部的处理机制上来说,有很大的差别。 这主要涉及到多列分组的问题。多列分组时指在 Group By 子句中使用两个或者两个以上的 列生成分组统计结果。当进行多列分组时,汇集于多个列的不同值产生数据统计结果。如上 面的例子中, 数据库就会根据年份、 月份、 供应商来生成统计结果。 如果用前者的表达方式, 则其先统计每个供应商的合计金额,在分类统计年、月的统计金额。简单的说,他们统计顺 序不同,但是显示结果相同。这也是第一点所说的,要把选择列表中的字段名、表达式等等 全部放入到 Group By 子句中的原因。只有如此,Group By 才会对这些字段进行分组统计。 只有如此才能够保证, 不会因为 Group By 子句中的参数顺序不同, 而显示不同的统计结果。 可见 Group By 分组语句其使用规范要比普通的 Select 等查询语句要求严格的多。数据 库管理员在使用 Group 语句进行数据分组统计时,一定要注意这些使用限制。否则的话在 利用这个分组语句的时候,难免会磕磕碰碰的。 注:1.分组函数只能出项在 having 和 order by 里而不是出现在 group by 和 where 里。 2.在 select 里出现的列和表达式,同时也要在 group by 里出现。