利用 GROUP BY 和 MAX 实现对表数据分组统计后的过滤查询(Oracle920)

        项目中遇到一个颇为复杂的数据库查询问题,想通之后又觉得挺简单的。其实还是对上学时就学过的 SQL 语言知识点不熟悉,比如 Group By。如果熟悉 SQL 语言,那么有很多筛选操作就可以放到数据库中完成,会大大减少客户端程序编写的代码量,也降低程序的复杂度。下面我举一个简单的例子,把分组查询的知识复习一下。



        假设表 TSalary 存储某项目组每个月的人员工资,该项目组人员流动性很强,某人可能 2 月在 3 月就不在了。

表结构如下:

--///////////////////////////////////////////////////////////////////////////////

SQL
> desc TSalary
 名称                                      是否为空? 类型
 
----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER(3)
 NAME                                      
NOT NULL VARCHAR2(8)
 
MONTH                                     NOT NULL NUMBER(6)
 SALARY                                    
NOT NULL NUMBER(8,2)

SQL
>

--///////////////////////////////////////////////////////////////////////////////


        其中 ID 列是用 sequence 实现的自增长主键列,月份 Month 用了数值型,格式为“200507”。

插入如下测试记录:

--///////////////////////////////////////////////////////////////////////////////

SQL
> select * from TSalary;

 ID NAME   
MONTH SALARY
--- ---- ------- ------
  1 张三  200501    701
  
2 李四  200501    901
  
3 王五  200501    801
  
4 赵六  200501   1001
  
5 张三  200502    702
  
6 李四  200502    902
  
7 王五  200502    802
  
8 李四  200503    903
  
9 王五  200503    803
 
10 张三  200504    704

已选择10行。

SQL
>

--///////////////////////////////////////////////////////////////////////////////


        查询需求:每个人最后拿到工资的那个月的工资记录

解决方法:

--///////////////////////////////////////////////////////////////////////////////

SQL
> select * from TSalary where id in (select max(id) from TSalary group by name);

 ID NAME   
MONTH SALARY
--- ---- ------- ------
  4 赵六  200501   1001
  
8 李四  200503    903
  
9 王五  200503    803
 
10 张三  200504    704

SQL
>

--///////////////////////////////////////////////////////////////////////////////


        分析:先用 group by 把表数据按 Name 分组,然后用 max 函数统计出每组最大的 ID 号,此最大 ID 号集合对应的记录集即为所求结果。



知识点复习:
        Group By: 将查询结果按某一列或多列值分组,值相等的为一组。可以在 Group By 子句后添加 Having 子句限定选择组的条件,只有满足 Having 条件的组才会被选择出来。

        分组函数:运算每一组记录,每一组返回一个结果。
AVG ([DISTINCT|ALL]n)  求平均
COUNT ({ *|[DISTINCT|ALL]expr}) 计数
MAX ([DISTINCT|ALL]expr) 取最大
MIN ([DISTINCT|ALL]expr) 取最小
SUM ([DISTINCT|ALL]n)  求和


附:



CREATE TABLE TSalary (
ID 
NUMBER(30NOT NULL,
Name 
VARCHAR2(8NOT NULL,
Month NUMBER(60NOT NULL,
Salary 
NUMBER(82NOT NULL,
CONSTRAINT PK_TSalary PRIMARY KEY (ID),
CONSTRAINT UQ_TSalary UNIQUE (Name, Month));

INSERT INTO TSalary VALUES1'张三'200501701 );
INSERT INTO TSalary VALUES2'李四'200501901 );
INSERT INTO TSalary VALUES3'王五'200501801 );
INSERT INTO TSalary VALUES4'赵六'2005011001 );
INSERT INTO TSalary VALUES5'张三'200502702 );
INSERT INTO TSalary VALUES6'李四'200502902 );
INSERT INTO TSalary VALUES7'王五'200502802 );
INSERT INTO TSalary VALUES8'李四'200503903 );
INSERT INTO TSalary VALUES9'王五'200503803 );
INSERT INTO TSalary VALUES10'张三'200504704 );
posted @ 2006-01-13 01:45  torome  阅读(1295)  评论(1编辑  收藏  举报