搜档网
当前位置:搜档网 › 双表查询,SQL语句使用

双表查询,SQL语句使用

双表查询,SQL语句使用
2009/04/17 09:59 A.M.
Select aid, a1, a2 from [表a]
union all
Select bid, b1, b2 from [表b]

使用Union的关键点:
一、查询结果是一个数据集,它的字段名以第1个Select后面的字段列表为准,后面的Select的字段列表需要与第1个的对齐(字段个数和数据类型相同,名称无所谓)

例如如下这句,就是增加一条记录。
Select aid, a1, a2 from [表a]
union all
Select bid, b1, b2 from [表b]
Union
select 0, '111', '222'

如下会出错,因为第一个Select中的字段 111 为整型,会造成[表b]的b1字段内容强行向整型转换,转换会失败:将 varchar 值 'b11' 转换为数据类型为 int 的列时发生语法错误。
select 0, 111, '222'
Union
Select bid, b1, b2 from [表b]

二、union all中的“All”不加的话,是自动剔除重复的记录(重复的记录只保留1条),加上“All”则会保留所有数据。
---------------------------------
按问题补充:1)让查询结果添加到一张新表里面;2)按某个条件查询,比如查询出结尾为22的数据。显示a22 b22:

只需要增加几个子句就可以了:

1)将查询结果放到新表:
Select aid, a1, a2 into [新表名] from [表a]
union all
Select bid, b1, b2 from [表b]
--关键点:SELECT INTO 必须是包含 UNION 运算符的 SQL 语句中的第一个查询。

2)增加查询条件:
Select aid, a1, a2 from [表a] where a2 like '%22'
union all
Select bid, b1, b2 from [表b] where b2 like '%22'
--关键点:每个子查询都要单独增加相应的查询条件!
-----------------------
对于“超时时间已到,……”:可能原因是:1、数据量过大;2、SQL的超时设置不够长。所以你可以尝试把SQL的超时设置长一些,比如2分钟;再就是把这个Union拆成两句来分别执行:
Select aid, a1, a2 into [新表名] from [表a]
Insert into [新表名] Select bid, b1, b2 from [表b]
如果还超时,那就复杂了,可能数据量太大、其他性能、索引、等综合检查了。

对于增加自增长字段的问题,是这样的,在Select into这种方式生成新表时,是无法指定自增长字段的。所以办法就是:先建立好表,再用Insert into的方式向里面插入数据:
CREATE TABLE dbo.NewTABLE
(
Myid int NOT NULL IDENTITY (1, 1),
oid int NULL,
A varchar(50) NULL,
B varchar(50) NULL
) ON [PRIMARY]
GO
Insert into [NewTABLE](oid,A,B) Select aid, a1, a2 from [表a]
Insert into [NewTABLE](oid,A,B) Select bid, b1, b2 from [表b]
Go
----------------------------------
“单纯的查询时候定义自增列”,这个据我所知是不行的,不知SQL 2005是否有此功能。因为查询的结果总是来源于现有数据或常数,且SQL的记录是没有行号概念的。
看能否从现有数据中的某一列通过某种计算得到一个貌似自增

的结果。类似:
select *, 一个公式(某列) as MyID from [tablename]

--------------------------------------------------------------------------------------

有关数据库的一写操作:

CREATE TABLE Student
(Sno CHAR(5) NOT NULL UNIQUE,
Sname CHAR(20),
Ssex CHAR(1),
Sage INT,
Sdept CHAR(15));
插入记录:
insert into Student (Sno,Sname,Ssex,Sdept) values('aaa','mary','f','172');
删除记录:
delete from Student where Sno = 'aaa';
注:只需要删除一个主键就可以了。其他的记录会相应的删除掉。
删除表中一个字段:
ALTER TABLE Student DROP column Ssex; 列名;
修改表中的那一行数据:
原来的记录:
Sno Sname Ssex Sdept
aaa mary f 172
update Student set Sname='mary1', Ssex='m' where Sno='aaa';
修改后:
Sno Sname Ssex Sdept
aaa mary1 m 172


desc倒叙排列:
建立索引:
create unique index Sno on Student(Sno);
索引的一点好处:在查询时候比较方便,在存在的所有记录中查找一个Sno=1的时候!建立索引的表中就直接查找Sno项比较它是否=1找到后查相关的记录就比较快。没有建立索引的需要把所有信息都查找一遍,再在其中找Sno字段,再比较其值=1的相关记录。

默认是ASC。
按表中哪个字段倒叙排序:
select * from Student order by Sno desc;
注意:要排序的字段必须是int型。

设置成自增长的字段在插入数据的时候不需要插入该字段的值:
select * from Student order by Sno desc;
原来没有设置成自增长插入数据命令:
insert into Student (Sno,Sname,Ssex,Sdept) values('aaa','mary','f','172');
将int型的Sno字段设置成自增长后
insert into Student (Sname,Ssex,Sdept) values('mary1','f','172');
insert into Student (Sname,Ssex,Sdept) values('mar1y','f','172');
insert into Student (Sname,Ssex,Sdept) values('ma1ry','f','172');
insert into Student (Sname,Ssex,Sdept) values('m1ary','f','172');

在表中的排序如下:
Sno Sname Ssex Sdept
1 mary1 f 172
2 mar1y f 172
3 ma1ry f 172
4 m1ary f 172
/*********************************************************************************
2006.7.20
*********************************************************************************/
查询表中记录总数:(无字段名字)
select count() from usertable;
或:(userid 为字段名字,结果是字段的总行数)
select count(*) userid from Student;

查询字段的平均值:
selecet avg(Sno) from Student;
select avg(字段名)from 表名;

给出查询的字段的平均值取别名:
select avg(字段名) as (别名) from (表名);

查找指定的字段的其他字段
select Sdept,Ssex,Sname
from Student
where Sno=3;
(where Sname='mary1';或则where Sname like 'mary1';)

在between语句查询的都是在and之间的所有值而IN语句则必须是in括号里面的值.
select Sno,Ssex,Sname from Student where Sdept betwee

n 180 and 190;

select Sno,Ssex,Sname from Student where Sdept in (172,190);


查询Student表中的所有的名字中的Sno和Ssex值.
select Sno,Ssex from Student where Sdept >= 170 and Sname like '%%';
注:%%之间是把所有的String类型的值



like和where条件查询
select last_name,salsry,department_id from employees where last_name like 'G%' and salary>3000;

查询Student表中的所有的名字中间有mary的所有名字对应的的Sno和Ssex值.
select Sno,Ssex from Student where Sdept >= 170 and Sname like '%mary%';
注:mary1,1mary,marydsajdh,等.

注意:and or not 用的时候,and是用在连接并列条件的2个不同的字段
or是用在选择的2个不同的字段之间,not一般用于not in(180,190)之间.
order by 和asc|desc的一点不同:
order by是按先进先排,desc是先进后排,asc和desc是排列顺序不一样.



disctinct条件查询
distinct 这个关键字来过滤掉多余的重复记录只保留一条,

select distinct name from table 表示将返回table表中name字段不重复的所有字段的集合。

注:distinct必须放在开头,select id distinct name from table 是错误的!

-------------------------------------------------------------------------------------
表TEST_1:
id name1 name2
9 aaa 11
8 bbb 22
3 ccc 33
4 ccc 44
5 bbb 55
6 ddd 66
7 eee 77
-------------------------------------------------------------------------------------

select distinct(name1) from test_1

结果:
name1
aaa
bbb
ccc
ddd
eee
distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的集合,而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段,而无法返回其它字段,即上表中只能返回name1字段的所有不重复记录集合。

-------------------------------------------------------------------------------------
如果现在想查询出表test_1中所有name1不重复的id和name1字段的记录呢?

select distinct name, id from table

结果:
name1 id
aaa 9
bbb 5
bbb 8
ccc 3
ccc 4
ddd 6
eee 7

并不是我们所想要的结果

select distinct name,id from table 作用了两个字段,也就是必须得id与name都相同的才会被排除,即返回去除table表中id和name两个字段同时相同情况下所有集合。
-------------------------------------------------------------------------------------

如果现在想查询出表test_1中所有name1不重复的所有字段的记录呢?

对于
select * from test_1 where name1 in (select distinct name1 from tablename)
等价于
select * from test_1 where name1 in ('aaa','bbb','ccc','ddd','eee')
我们很可能认为它是可行的,但实际上结果却是:

id name1 name2
9 aaa 11
8 bbb 22
3 ccc 33
4 ccc 44
5 bbb 55
6 ddd 66
7 eee 77

正确sql应该是:
select * from test_1 inner

join (select min(id) as id from test_1 group by name1 order by id ) T on test_1.id = T.id

min(id)或max(id)都行,order by id 可要可不要.这里用内连接实现联合查询,也可以用where语句

select * from test_1 ,(select min(id) as id from test_1 group by name1 order by id ) where test_1.id = T.id

-------------------------------------------------------------------------------------

**********************************************************************************
联合查询
**********************************************************************************
查询表中的各个字段的值
select Sno,Sname,Ssex,Sdept from Student;

多表查询(2个表,publishtable和publishtable,给表起了别名)
select https://www.sodocs.net/doc/409131668.html,erid,u.age,https://www.sodocs.net/doc/409131668.html,ername,p.publishname from usertable u,publishtable p where https://www.sodocs.net/doc/409131668.html,erid = p.publishid;

多表查询(3个表employees,departments和locations表,给表起别名)
(从多表中查询出所有姓smith的雇员的名字,所在部门以及部门所在的城市)
select e.first_name,https://www.sodocs.net/doc/409131668.html,st_name,d.department_name,l.city from employees e,departments d,locations l where e.department_id = d.department_id and d.location_id = l.location_id and https://www.sodocs.net/doc/409131668.html,st_name = 'smith';


***********************************************************************************
联合查询
***********************************************************************************

等值连接
/*将books表和表bookstype中的信息联合查询,条件是联系键相等*/
select * from books,bookstype where bookstype.typeid = books.typeid


内连接
/*将books表和表bookstype中的信息联合查询,条件是联系键相等,和等值连接等价*/
select * from books inner join bookstype on books.typeid = bookstype.typeid

左外连接

/*将books表和表bookstype中的信息联合查询,包括在books表中没有和bookstype表关联的信息*/
select * from books left outer join bookstype on bookstype.typeid = books.typeid

右外连接

/*将bookstype表和books表中的信息联合查询,包括在bookstype表中没有和books表关联的信息*/
select * from books right outer join bookstype on bookstype.typeid = books.typeid

全连接

/*将bookstype表和books表中的信息联合查询,包括在books表中没有和bookstype表关联的信息以及在bookstype表中没有和books表关联的信息*/

select * from books full outer join bookstype on bookstype.typeid = books.typeid


***********************************************************************************
联合查询
***********************************************************************************
多表查询应该注意的几点:
多表查询和单表查询的不同在于多表查询在查询某个字段的时候应该带上表名
格式是:表名.字段名,表名.字段名
select bbs.id,https://www.sodocs.net/doc/409131668.html,,bbs.dep,bbsr.id,https://www.sodocs.net/doc/409131668.html,
from bbs,bbsr
where bbs.id=bbsr.id;
一般的在多表查询

中的表名取的麻烦用别名来代替
如下:
select b.id,https://www.sodocs.net/doc/409131668.html,,b.dep,c.id,https://www.sodocs.net/doc/409131668.html,
from bbs as b ,bbsr as c // from bbs b,bbsr c***注意取别名也可以用空格或则用as.
where b.id=c.id;

*************************************************************************************
分组查询
*************************************************************************************

在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息,另外,可以使用having子句限制返回的结果集。group by 子句可以将查询结果分组,并返回行的汇总信息SQLServer 按照group by 子句中指定的表达式的值分组查询结果。

-------------------------------------------------------------------------------------
分组查询一般是用来进行统计需求的,要进行分组查询必须使用group by子句或having子句,在分组统计时要用到SQL的多行存储函数。在where条件中不能使用多行存储函数.

查询语句的select 和group by ,having 子句是聚组函数唯一出现的地方,在where 子句中不能使用聚组函数。

在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数.
------------------------------------------------------------------------------------


部门表department:

department_id department_name
10 开发部
20 测试部
30 用服部
40 财务部
50 培训部

雇员表employees:(department_id为外键)

id employees_name department_id
1 cheng 10
2 zhou 50
3 liguo 10
4 wang 20
5 feng 30
6 ling 30
7 wu 20
8 tang 20
9 yang 40
10 tan 50
------------------------------------------------------------------------------------

按部门编号统计出表employees中的每个部门的人数(group by分组查询)
select department_id, count(*) from employees
group by department_id;

显示出部门人数少于5人的部门编号以及人数( 按照department_id来分组,having count(*)<5做为限制条件 )
select department_id 部门号, count(*) 部门人数 from employees
group by department_id
having count(*)<5;
--------------------------------------
(注意:having必须在group by子句的后面)
--------------------------------------
图:
部门号 部门人数
------------------------------
10 2
20 3
30 2
40 1
50 2
-------------------------------------------------------------------------------------
where子句和having子句可以同时使用,where子句是对要分组的行进行过滤,即选择要分组的行;
而having子句是对分组后的数据进行过滤。此时where子句必须在group by...having子句之前
-------------------------------------------------------------------------------------
显示出所有工资大于5000,且部门人数大于5个的部门号,部门

最低工资和部门人数

select department_id 部门号(记住department_id 和部门号之间要空格), min(salary) 最低工资,count(*) 部门人数 from employees
where salary >5000
group by department_id
having count(*)>5;

图:
--------------------------------------
部门号 最低工资 部门人数
80 6100 34
100 6800 6

group by 按照哪个字段来排序查询,一般的group by和having一起使用,注意在查询中只能查询与group by和having有关的字段。
--------------------------------------

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。


having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。


查询每个部门的每种职位的雇员数(待测试...)
select deptno,job,count(*) from emp group by deptno,job;


*********************************************************************************
数据排序
*********************************************************************************

order by子句中可以用asc(升序)和desc(降序)来完成相应的排序,默认时是按找asc(升序)。
---------------------------------------------------------------------------------
显示出所有工资大于5000,且部门人数大于5个的部门号,部门最低工资和部门人数,并要求按照部门人数降序排序.

select department_id 部门号(记住department_id 和部门号之间要空格), min(salary) 最低工资,count(*) 部门人数 from employees
where salary >5000
group by department_id
having count(*)>5
order by count(*)desc
-------------------------------------------------------------------
(注意:当对分组查询后的结果进行排序时,order by 必须在group by之后)
-------------------------------------------------------------------

图:
--------------------------------------
部门号 最低工资 部门人数
80 6100 34
100 6800 30
90 6500 28
70 6300 25


*******************************************************************************
子查询
*******************************************************************************

-----------------------------------------------------------------------------------------------------
子查询是一个在select查询中含有其他的select语句,子查询通常用在where子句中,即将一个查询结果做为查询的条件.
-----------------------------------------------------------------------------------------------------
统计表employees中所有工资小于平均工资的人数
select count(*)工资 from employees
where salary <
(select avg(salary) from employees)
图:
----------------
工资
56
49


36

Select MIN(Salary),Manager_id
from Employee
group by Manager_id
having MIN(Salary) >
(Select MIN(Salary)
From Employee
where Manager_id=004);

注意在多表查询中返回的值应该是一个唯一确定的值,而不应该是多中值。
select Employee_id,Last_name,Salary,Manager_id
from Employee
WHERE Salary>
(select Salary
from Employee
where Manager_id=003)
and
Last_name= (select Last_name
from Employee
where Last_name like 'mary');

注意在any,or,all的区别:
Select Salary,Manager_id,Last_name,Employee_id
from Employee
where Salary < any
(Select Salary
From Employee
where Manager_id=005);

Select Salary
From Employee
where Manager_id=005;返回的是2000,2500
就是在工资中小于2000.2500其中一个就可以了,而ALL则必须是小于2000和2500其中任何一个
。而or则是和and用在一起的.

******************************************************************************************
集合运算
******************************************************************************************

---------------------------------------------------------------------------------
集合运算是将2个或多个子查询结果进行(并union),交(intersect)和减(minus)
---------------------------------------------------------------------------------
(并union):
select employee_id,empname from emp1
union
select employee_id,name from emp2

图:
-----------------
employee_id empname
100 king1
1000 king2
1000 king3
10000 king4
100000 king5
1000000 king6

注:使用union,重复行只包括一个,当使用union all时将包括重复行

交(intersect):2个或多个子查询的公共行
select employee_id,empname from emp1
intersect
select employee_id,name from emp2

减(minus):从第一个查询结果中去掉出现在第二个查询结果中的行:
select employee_id,empname from emp1
minus
select employee_id,name from emp2


*****************************************************************************************
视图,存储过程和触发器
*****************************************************************************************

创建视图:(查询数据,用于系统统计报表)
create view dept_sum_vu
(name,minsal,maxsal,avgsal)
as select d.department_name,min(e.salary),max(e.salary),avg(e.salary)
from employees e,departments d
where e.department_id = d.department_id
group by d.department_name;

存贮过程,触发器和删除外键

1).存贮过程:
存贮过程的路径:打开Stored Procedures中new一个新的Stored Procedures,中间填写代码,代码如下:
CREATE PROCEDURE sa.bbsTest AS

select Bbsid ,content , area_id , name FROM BBs a JOIN bbs_area b
on a.area_id = b.id


CREATE PROCEDURE bbsTest AS

select Bbsid ,content , area_id , name FROM BBs a JOIN bbs_area b
on a.area_id = b.id

2).触发器

打开用户表项,点设计表,选中其中一

个字段,右键task点manager triggers,在弹出的表单中写代码:
CREATE TRIGGER [tD_bbs_area] ON [dbo].[bbs_area]
FOR DELETE
AS
BEGIN
DELETE rebbs
FROM bbs, deleted
WHERE rebbs.bbs_id = bbs.bbsid
AND bbs.area_id = deleted.id

DELETE bbs
FROM deleted
WHERE bbs.area_id = deleted.id

END

3).删除外键
打开用户表项,点设计表,选中其中一个字段,右键relationships,在弹出的主键和外键中选择就可以了.
删除外键,需要先删除主键表里面的有关外键的字段,再来删除外键的有关字段.



 用ORDER BY对查询结果排序

ORDER BY子句让数据库对查询结果排序,这样你就无须自己编写应用程序进行“手工”排序了。ORDER BY子句必须放在查询语句的结尾。其基本用法如下:

SELECT * FROM Contacts ORDER BY first_name;

你可以随意在任何选择语句中使用ORDER BY 子句返回多列结果。你还可以用它连接其他子句:

SELECT first_name, last_name FROM Contacts WHERE first_name BETWEEN ‘a’ AND ‘k’ ORDER BY last_name;

你可以对多列数据排序。优先顺序按从左到右依次降低,所以查询语句中各列的排列顺序很重要。

SELECT * FROM Contacts ORDER BY company, last_name, first_name;

查询结果默认按数字或者字母的升序排序。你可以在ORDER BY 子句后面加上DESC关键词改成降序排列。在下面的例子中,最高的net_amount排在最先(降序)。假如两行或者两行以上数据都包含了同样的net_amount值,那么同行中last_name值在字母表中最先出现的排先,因为last_name一列还是按照升序排序的。

SELECT * FROM Sales ORDER BY net_amount DESC, last_name, first_name;

在按照定义的列名排序以后,大多数数据库随后将按照数据表内的第一列排序然后顺序向右再排序。具体的实现各有变化,因此,如果排序在应用中比较重要那么你应该明确地定义所要排序的列。

另外一值得注意的问题是,采用ORDER BY子句(以及WHERE子句),你正在用来排序结果的数据列并不一定得是返回结果集合的一部分。只要所有引用的列都在数据表内存在则下例完全有效:

SELECT company, first_name, net_amount FROM Sales ORDER BY start_date, last_name;

DISTINCT返回不重复结果

DISTINCT关键词只返回结果集合内不重复的数据行。例如,有时你可能需要找出Sales表内的公司,但是你又不想看见每个条目。于是你可以用DISTINCT对应每一公司名返回一行数据:

SELECT DISTINCT company FROM Sales;

在使用DISTINCT时,它适用于所有的请求列。如果你打算列出表内的所有销售人员和他们所代表的公司而非每一销售记录,那么你可以使用下列语句。注意,这样操作还可能返回同一公司的

若干条目等等。

SELECT DISTINCT company, last_name, first_name FROM Sales;

你还可以在对结果缩小范围和进行排序时结合SELECT语句使用DISTINCT。为了确定显示的内容,数据库首先会证实精练的请求是否匹配数据行,然后应用DISTINCT功能。在全部结果集合都得以确定之后即处理ORDER BY子句。如下例所示,只有net_amount大于100的数据行才被返回。由于DISTINCT保留遇见的第1个匹配查询条件的数据行而丢弃其他匹配行,所以ORDER BY语句所引用的net_amount看起来就好象产生了随机的结果。

SELECT DISTINCT company, last_name, first_name FROM Sales WHERE net_amount > 100 ORDER BY company, net_amount;

函数应用逻辑

返回单一值的函数称做聚集函数(aggregate function)。通过应用程序访问下列聚集函数的结果时,包含结果的“字段名”就是你所使用的实际函数。例如,在分析你的数据库结果时,结果数组的键值可能如下所示:

$keyname = “COUNT(*)”;

$resultkey = “AVG(net_amount)”;

COUNT

COUNT函数计算出结果集合中的数据行数。和其他函数一样它接受一个参数。以下的基本示例能告诉你数据表内的行数:SELECT COUNT(*) FROM Sales;

你也可以用它来计算任何结果集合中的行数。

SELECT COUNT(*) FROM Sales WHERE net_amount > 100;

如果你想看看某特定列有多少行包含非空值,那你不妨对该列使用COUNT函数。注意,除非数据库设置为字段为空时缺省填充NULL否则将返回表内数据行的总数。另外,列出的列在超出一个的情况下会引起错误。

SELECT COUNT(company) FROM Sales;

COUNT还可以用来计算DISTINCT结果集合中的行数。

SELECT COUNT(DISTINCT company, last_name) FROM Sales;

COUNT语句通常用在程序中确定FOR循环的循环次数。

AVG

AVG返回某列所有字段的平均值,该列必须是数字数据类型。该函数用列的名字作为其参数,如果列字段数据类型是非数字类型的则函数返回“0”。SELECT AVG(net_amount) FROM Sales;

你可以结合子句限制该函数的应用范围。

SELECT AVG(net_amount) FROM Sales WHERE company LIKE ‘%ABCD Co%’;

就象所有聚集函数一样,ORDER BY语句将被忽略。

SUM

SUM的工作方式和AVG差不多,只不过该函数返回结果集合中所有字段值的和。

SELECT SUM(net_amount) FROM Sales WHERE net_amount > 100;

AVG、SUM、MIN和MAX函数在没有指定列的情况下都会返回错误,所以你不能使用“*”通配符。

MIN

MIN返回指定列中最小的非空值。如果指定列是数字数据类型则结果将是最小的数字。如果它是一种字符串数据类型则函数将返回按字

母表顺序出现的第1个值。SELECT MIN(net_amount) FROM Sales WHERE last_name = “Smith”;

SELECT MIN(last_name) FROM Sales;

MAX

MAX的工作方式和MIN函数一样,只不过该函数返回最大的非空值。该函数也可以用于字符串或者数字列

SELECT MAX(net_amount) FROM Sales;

SELECT MAX(company) FROM Sales WHERE net_amount > 100;

MAX函数有时还用在包含自动递增键字段的列上确定下一条目的键ID。除非你正在运行一个非公开的数据库,否则在使用这一信息插入下一条目时务必谨慎,以防其他用户先你执行数据操作。

GROUP BY 令函数更有用

虽然以上提到的所有这些函数都能提供相当有用的信息,但是,如果有GROUP BY子句帮忙的话更能让你在列的字段子集中应用这些函数。不要对你的Sales表中每一家公司一次又一次地执行MAX函数查询——你完全可以带GROUP BY子句获得同样的结果:

SELECT company, MAX(net_amount) FROM Sales GROUP BY company;

这样做可以获得每家公司net_amount的的最大值。在选择多列名的时候也可以采用该语句,你还可以用多列来对函数结果分组。

下面的例子演示了以上各种方式。首先,包括GROUP BY子句可以令你指定要显示的其他列。然而,你得知道这个例子将返回在组中遇到的第1个last_name值;Sum( net_amount )将显示全部公司的结果而不仅仅针对匹配姓氏的数据行。这是因为,我们只使用了Company字段来定义我们的组。

SELECT company, last_name, SUM(net_amount) FROM Sales GROUP BY company;

在上面的例子中,last_name列实际上并没有提供什么有用的信息,但这样做是为了在下一个例子中要用到的功能做准备。你可以创建多列定义的组。这样就可以在结果集合中产生针对特定行的函数结果,而结果集合则是由所有指定的GROUP BY列联合起来创建的:

SELECT company, AVG(net_amount), last_name FROM Sales GROUP BY company, last_name;

上面的例子给每家公司中每一姓氏给出了平均的net_amount。你列出GROUP BY列的顺序控制着结果的排序,但是实际的函数值结果是一样的。

下面的例子表明如何组织结果而不显示分组的列。在有些场合这样做是很有用的,例如,如果要显示个人的销售量但却不显示姓名就能用上下面的例子了:

SELECT company, COUNT(sale_id) FROM Sales GROUP BY company, last_name;

限制使用GROUP BY的查询

如你在以上示例中所看到的那样,你可以结合WHERE字句利用以上的概念限制查询的范围。WHERE子句会首先被计算,然后执行函数。在使用组的时候就是这样的。

SELECT company, AVG(net_amount), FROM Sales WHERE net_amount > 100 GROUP BY com

pany;

上面的例子只对那些满足WHERE限制条件的数据行适用AVG函数。注意,WHERE子句必须放在GROUP BY子句之前。你还可以用HAVING语句对分组计算之后限制返回的结果集合。

SELECT company, AVG(net_amount), FROM Sales WHERE last_name BETWEEN ‘a’ AND ‘m’ GROUP BY company HAVING AVG(net_amount) > 500;

上面的语句计算每家公司net_amount的平均值,而且只计算那些姓氏满足限制条件的销售人员的销售量,同时只显示大于500的结果。

相关主题