使用Group By注意事项

时间:2022-09-08 19:29:45

当查询中存在group by子句时,select列表(或是having子句)中只能存在分组函数,或是出现在group by子句中的字段。

这里说的,“出现在group by子句中的字段”具体有两种形式出现:

1、select列表里直接出现一个以该字段名为列名的列,如:

select  La from test group by La;

1、select列表里出现一个非分组函数的函数的列,如:

select  La ,contact(La,La)from test group by La;

select  La ,contact(La,‘two’)from test group by La;

select  La ,contact(La,&tt)from test group by La;

注释:

当查询中存在group by子句时,非分组函数的参数值只能是from子句里各个表中出现在group by子句中的字段(变量)。而from子句里各个表中不出现在group by子句中的字段(变量)则不能为非分组函数的参数值,此时。而其他不是属于在表定义的变量(即表的列)的的变量,如上述的替换变量&tt,则可以为非分组函数的参数值。常量,可以为非分组函数的参数值,此时。

总之,当查询中存在group by子句时,只有from子句里各个表中不出现在group by子句中的字段(变量)不能为非分组函数的参数值。

当查询中存在group by子句时,分组函数,其参数值可以来自from子句里各个表中不出现在group by子句中的字段(变量)。

当查询中存在group by子句时,select列表中出现在group by子句中的字段组合值都是不重复的一条。例如,

select  La,Lb from test;

La  Lb

--    ---

a    3

a    9

b    2

b    3

b   12

select  La,sum(Lb) from test group by La;

La     sum(Lb)

--       ---

a       12

b       17

test里La为a,b值都是多条,经过group by后,结果集里La为a,b值总是都为一条。

这里,以select  La,sum(Lb) from test group by La;为例子,来描述group by的处理过程。大概过程如下:

先对test表上的数据行按列La进行排序即order by,再对非在group by子句中的字段进行聚合函数操作(如果group by子句所在select语句中存在聚合函数的话,会执行该步骤;不存在的话,就跳过不执行该步骤),这样,就对应输出一个列La的值(经过distinct操作这个步骤处理)和一个聚合函数返回值构成结果集A里的一行。聚合函数返回值都是一个的。

而select  La ,contact(La,‘two’)from test group by La;里的非分组函数contact所用的La的值是来自在该SQL语句中group by的处理过程执行完毕后对应输出的结果集A上一个列La的值,即非分组函数contact在结果集A基础上再进行处理获得该sql语句的最终一步结果集B。

再看如下例子,

SQL> select * from test; 

COUNTRY CITY 
-------------------- -------------------- 
中国 台北 
中国 香港 
中国 上海 
日本 东京 
日本 大阪

定义一个函数 
create or replace function str_list( str_in in varchar2 )--分类字段 
return varchar2 
is 
str_list varchar2(4000) default null;--连接后字符串 
str varchar2(20) default null;--连接符号 
begin 
for x in ( select TEST.CITY from TEST where TEST.COUNTRY = str_in ) loop 
str_list := str_list || str || to_char(x.city); 
str := ', '; 
end loop; 
return str_list; 
end; 
使用: 
SQL> select t.country,str_list(t.country) from test t GROUP BY t.country; 

COUNTRY STR_LIST(T.COUNTRY) 
-------------------- ----------------------- 
中国 台北, 香港, 上海 
日本 东京, 大阪 
这个时候,使用分组和求唯一都可以满足要求。它的原理就是,根据唯一的分组字段country,在str_list函数里面再次查询该字段对应的所有被合并列,使用PL/SQL将其合并输出,也就是说,在str_list函数里执行的select TEST.CITY from TEST where TEST.COUNTRY = str_in这个sql语句(对表test再次做查询)和select t.country,str_list(t.country) from test t GROUP BY t.country; 这个sql语句是相当于相互独立的两个sql语句在执行,前者不受后者里有GROUP BY 的影响,在执行str_list函数(里的select TEST.CITY from TEST where TEST.COUNTRY = str_in这个sql语句)时,外层的select t.country,str_list(t.country) from test t GROUP BY t.country; 这个sql语句除了select子句还没执行完(select子句执行完就获得该select语句的最终结果集了)外,其他子句都已经执行完,即 GROUP BY子句已经执行完获得了结果集A了,而外层的这个sql语句的select子句里执行的正是str_list函数。(select子句里的函数是否没查到一条数据行就立刻执行一次,而不是经过where等子句筛选出一个结果集后在执行,如case then?)

这两个sql语句也可以相当于前者是后者里的子查询,外层语句先开始执行,但子查询都是先于外层语句执行完毕的,故前者不受后者里有GROUP BY 的影响。(执行个带子查询和GROUP BY的查询语句试试,两层查询都对同个表?)