建表:
DEPARTMENTS:
DEPARTMENT_ID(primary key),
DEPARTMENT_NAME,
LOCATION
EMPLOYEES:
EMPLOYEE_ID(primary key),
EMPLOYEE_NAME,
EMPLOYEE_JOB,
MANAGER,
SALARY,
DEPARTMENT_ID
1. 列出EMPLOYEES表中各部门的部门号,最高工资,最低工资
select max(SALARY) as 最高工资,min(SALARY) as 最低工资,DEPARTMENT_ID from EMPLOYEES group by DEPARTMENT_ID;
2.列出EMPLOYEES表中各部门EMPLOYEE_JOB为'CLERK'的员工的最低工资,最高工资
select max(SALARY) as 最高工资,min(SALARY) as 最低工资,DEPARTMENT_ID as 部门号 from EMPLOYEES where EMPLOYEE_JOB = 'CLERK' group by DEPARTMENT_ID;
3.对于EMPLOYEES中最低工资小于1000的部门,列出EMPLOYEE_JOB为'CLERK'的员工的部门号,最低工资,最高工资
select max(SALARY) as 最高工资,min(SALARY) as 最低工资,DEPARTMENT_ID as 部门号 from EMPLOYEES as b where EMPLOYEE_JOB ='CLERK' and 1000>(select min(SALARY) from EMPLOYEES as a
where a.DEPARTMENT_ID = b.DEPARTMENT_ID) group by b.DEPARTMENT_ID
4.根据部门号由高而低,工资有低而高列出每个员工的姓名,部门号,工资
select DEPARTMENT_ID as 部门号,EMPLOYEE_NAME as 姓名,SALARY as 工资 from EMPLOYEES
order by DEPARTMENT_ID desc,SALARY asc
5.列出'张三'所在部门中每个员工的姓名与部门号
select EMPLOYEE_NAME,DEPARTMENT_ID from EMPLOYEES where DEPARTMENT_ID =
(select DEPARTMENT_ID from EMPLOYEES where EMPLOYEE_NAME = '张三')
6.列出每个员工的姓名,工作,部门号,部门名
select EMPLOYEE_NAME,EMPLOYEE_JOB,EMPLOYEES.DEPARTMENT_ID,DEPARTMENTS.DEPARTMENT_NAME
from EMPLOYEES,DEPARTMENTS where EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
7.列出EMPLOYEES中工作为'CLERK'的员工的姓名,工作,部门号,部门名
select EMPLOYEE_NAME,EMPLOYEE_JOB,DEPARTMENTS.DEPARTMENT_ID,DEPARTMENT_NAME
from EMPLOYEES,DEPARTMENTS where DEPARTMENTS.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID and DEPARTMENT_JOB = 'CLERK'
8.对于EMPLOYEES中有管理者的员工,列出姓名,管理者姓名(管理者外键为MANAGER)
select a.EMPLOYEE_NAME as 姓名,b.EMPLOYEE_NAME as 管理者 from EMPLOYEES as a,EMPLOYEES as b
where a.MANAGER is not null and a.MANAGER = b.EMPLOYEE_ID
9.对于DEPARTMENTS表中,列出所有部门名,部门号,同时列出各部门工作为'CLERK'的员工名与工作
select DEPARTMENT_NAME as 部门名,DEPARTMENTS.DEPARTMENT_ID as 部门号,EMPLOYEE_NAME as 员工名,EMPLOYEE_JOB as 工作
from DEPARTMENTS,EMPLOYEES where DEPARTMENTS.DEPARTMENT_ID *= EMPLOYEES.DEPARTMENT_ID and EMPLOYEE_JOB = 'CLERK'
10.对于工资高于本部门平均水平的员工,列出部门号,姓名,工资,按部门号排序
select a.DEPARTMENT_ID as 部门号,a.EMPLOYEE_NAME as 姓名,a.SALARY as 工资 from EMPLOYEES as a where a.SALARY>(select avg(SALARY) from EMPLOYEES as b where a.DEPARTMENT_ID = b.DEPARTMENT_ID) order by a.DEPARTMENT_ID
11.对于EMPLOYEES,列出各个部门中平均工资高于本部门平均水平的员工数和部门号,按部门号排序
select count(a.SALARY) as 员工数,a.DEPARTMENT_ID as 部门号 from EMPLOYEES as a where a.SALARY>(select avg(SALARY) from EMPLOYEES as b where a.DEPARTMENT_ID = b.DEPARTMENT_ID)
group by a.DEPARTMENT_ID order by a.DEPARTMENT_ID
12.对于EMPLOYEES中工资高于本部门平均水平,人数多与1人的,列出部门号,人数,按部门号排序
select count(a.EMPLOYEE_ID) as 员工数,a.DEPARTMENT_ID as 部门号,avg(SALARY) as 平均工资 from EMPLOYEES as a where (select count(c.EMPLOYEE_ID) from EMPLOYEES as c where c.DEPARTMENT_ID = a.DEPARTMENT_ID
and c.SALARY>(select avg(SALARY) from EMPLOYEES as b where c.DEPARTMENT_ID = b.DEPARTMENT_ID))>1 group by a.DEPARTMENT_ID order by a.DEPARTMENT_ID
13. 对于EMPLOYEES中低于自己工资至少5人的员工,列出其部门号,姓名,工资,以及工资少于自己的人数
select a.DEPARTMENT_ID,a.EMPLOYEE_NAME,a.SALARY,(select count(b.EMPLOYEE_NAME) from EMPLOYEES as b
where b.SALARY < a.SALARY) as 人数 from EMPLOYEES as a where (select count(b.EMPLOYEE_NAME) from EMPLOYEES as b where b.SALARY<a.SALARY)>5
三、SQL基础题( 共30分) 设教学数据库Education有三个关系: 学生关系S(SNO,SNAME,AGE,SEX,SDEPT);学习关系SC(SNO,CNO,GRADE);课程关系C(CNO,CNAME,CDEPT,TNAME) 查询问题: (1)检索计算机系的全体学生的学号,姓名和性别; 3分 (2)检索学习课程号为C2的学生学号与姓名; 3分 (3)检索选修课程名为“DS”的学生学号与姓名; 3分 (4)检索选修课程号为C2或C4的学生学号; 3分 (5)检索至少选修课程号为C2和C4的学生学号; 3分 (6)检索不学C2课的学生姓名和年龄; 5分 (7)检索学习全部课程的学生姓名; 5分 (8)查询所学课程包含学生S3所学课程的学生学号。 5分 (1)检索计算机系的全体学生的学号,姓名和性别; SELECT Sno,Sname,Sex FROM S WHERE Sdept =’CS’; (2)检索学习课程号为C2的学生学号与姓名; 1.SELECT Sno,Sname FROM S WHERE Sno IN ( SELECT Sno FROM SC WHERE Cno=‘C2’) 2.SELECT S.Sno,Sname FROM S,SC WHERE S.Sno=SC.Sno AND SC.Cno=‘C2’; (3)检索选修课程名为“DS”的学生学号与姓名 本查询涉及到学号、姓名和课程名三个属性,分别存放在S和C表中,但S和C表没有直接联系,必须通过SC表建立它们二者的联系。 C → SC → S 基本思路: (1)首先在C表中找出“DS”课程的课程号Cno; (2)然后在SC表中找出Cno等于第一步给出的Cno 集合中的某个元素Cno; (3)最后在S关系中选出Sno等于第二步中Sno 集合中某个元素的元组,取出Sno 和Sname送入结果表列。 SELECT Sno,Sname FROM S WHERE Sno IN(SELECT Sno FROM SC WHERE Cno IN (SELECT Cno FROM C WHERE Cname=‘DS’)); (4)检索选修课程号为C2或C4的学生学号; SELECT Sno FROM SC WHERE Cno=‘C2’ OR Cno=‘C4’; (5)检索至少选修课程号为C2和C4的学生学号; SELECT Sno FROM SC X,SC Y WHERE X.Sno=Y.Sno AND X.Cno=‘C2’ AND Y.Cno=‘C4’ ; (6)检索不学C2课的学生姓名和年龄; A.SELECT Sname FROM S WHERE Sno NOT IN ( SELECT Sn FROM SC WHERE Cno=‘C2’); 或者 B.SELECT Sname FROM S WHERE NOT EXISTS ( SELECT * FROM SC WHERE SC.Sno=S.Sno AND Cno=‘C2’); (7)检索学习全部课程的学生姓名; 在表S中找学生,要求这个学生学了全部课程。换言之,在S表中找学生,在C中不存在一门课程,这个学生没有学。 SELECT Sname FROM S WHERE NOT EXISTS (SELECT * FROM C)
CREATE TABLE STUDENT (SNO VARCHAR(3) NOT NULL, SNAME VARCHAR(4) NOT NULL, SSEX VARCHAR(2) NOT NULL, SBIRTHDAY DATETIME, CLASS VARCHAR(5)) go CREATE TABLE COURSE (CNO VARCHAR(5) NOT NULL, CNAME VARCHAR(10) NOT NULL, TNO VARCHAR(10) NOT NULL) go CREATE TABLE SCORE (SNO VARCHAR(3) NOT NULL, CNO VARCHAR(5) NOT NULL, DEGREE NUMERIC(10, 1) NOT NULL) go CREATE TABLE TEACHER (TNO VARCHAR(3) NOT NULL, TNAME VARCHAR(4) NOT NULL, TSEX VARCHAR(2) NOT NULL, TBIRTHDAY DATETIME NOT NULL, PROF VARCHAR(6), DEPART VARCHAR(10) NOT NULL) INSERT INTO STUDENT (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (103 ,'陆君' ,'男' ,1974-06-03,95031); 1、 查询Student表中的所有记录的Sname、Ssex和Class列。 2、 查询教师所有的单位即不重复的Depart列。 3、 查询Student表的所有记录。 4、 查询Score表中成绩在60到80之间的所有记录。 5、 查询Score表中成绩为85,86或88的记录。 6、 查询Student表中“95031”班或性别为“女”的同学记录。 7、 以Class降序查询Student表的所有记录。 8、 以Cno升序、Degree降序查询Score表的所有记录。 9、 查询“95031”班的学生人数。 10、查询Score表中的最高分的学生学号和课程号。 11、查询‘3-105’号课程的平均分。 12、查询Score表中至少有5名学生选修的并以3开头的课程的平均分数。 13、查询最低分大于70,最高分小于90的Sno列。 14、查询所有学生的Sname、Cno和Degree列。 15、查询所有学生的Sno、Cname和Degree列。 16、查询所有学生的 Sname、Cname和Degree列。 17、查询“95033”班所选课程的平均分。 18、假设使用如下命令建立了一个grade 表: create table grade(low number(3,0),upp number(3),rank char(1)); insert into grade values(90,100,'A'); insert into grade values(80,89,'B'); insert into grade values(70,79,'C'); insert into grade values(60,69,'D'); insert into grade values(0,59,'E'); 现查询所有同学的Sno、Cno和rank列。 19、查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。 20、查询score中选学一门以上课程的同学中分数为非最高分成绩的记录。 21、查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。 22、查询和学号为108的同学同年出生的所有学生的Sno、Sname和Sbirthday列。 23、查询“张旭“教师任课的学生成绩。 24、查询选修某课程的同学人数多于5人的教师姓名。 25、查询95033班和95031班全体学生的记录。 26、查询存在有85分以上成绩的课程Cno. 27、查询出 “计算机系“教师所教课程的成绩表。 28、查询“计算机系”与“电子工程系“不同职称的教师的Tname和Prof。 29、查询选修编号为“3-105“课程且成绩至少高于选修编号为“3-245”的同学的Cno、Sno和Degree,并按Degree从高到低次序排序。 30、查询选修编号为“3-105”且成绩高于选修编号为“3-245”课程的同学的Cno、Sno和Degree. 31、查询所有教师和同学的 name、sex和birthday. 32、查询所有“女”教师和“女”同学的name、sex和birthday. 33、查询成绩比该课程平均成绩低的同学的成绩表。 34、查询所有任课教师的Tname和Depart. 35 查询所有未讲课的教师的Tname和Depart. 36、查询至少有2名男生的班号。 37、查询Student表中不姓“王”的同学记录。 38、查询Student表中每个学生的姓名和年龄。 39、查询Student表中最大和最小的Sbirthday日期值。 40、以班号和年龄从大到小的顺序查询Student表中的全部记录。 41、查询“男”教师及其所上的课程。 42、查询最高分同学的Sno、 Cno和Degree列。 43、查询和“李军”同性别的所有同学的Sname. 44、查询和“李军”同性别并同班的同学Sname. 45、查询所有选修“计算机导论”课程的“男”同学的成绩表 SQL语句练习题参考答案 1、 select Sname,Ssex,Class from Student; 2、 select distinct depart from teacher; 3、 select Sno as '学号',Sname as '姓名',Ssex as '性别',Sbirthday as'出生日期',Class as'班号'from student;
或 select Sno as 学号,Sname as 姓名,Ssex as 性别,Sbirthday as 出生日期,Class as 班号 from student; 4、 select * from score where degree between 60 and 80; 或select * from score where degree>=60 and degree<=80; 5、 select * from score where degree in (85,86,88); 6、 select * from student where class='95031'or Ssex='女'; 7、 select * from student order by class desc; 8、 select * from score order by cno asc ,degree desc; 或select * from score order by cno ,degree desc; 9、 select count(*) as CNT from student where class='95031'; 10、select Sno as '学号',cno as '课程号', degree as '最高分' from score where degree=(select max(degree) from score) 11、select avg(degree)as 课程平均分 from score where cno='3-105'; 12、 select cno,avg(degree) from score where cno like'3%'group by cno having count(*) >5; 13、select Sno from score group by Sno having min(degree)>70 and max(degree)<90; 14、select student.Sname,score.Cno,score.degree from student,score where student.Sno=score.Sno group by sno; 15、select x.Sno,y.Cname,x.degree from score x,course y where x.Cno=y.Cno; 16、select x.Sname,y.Cname,z.degree from student x,course y,score z where x.Sno=z.Sno and z.Cno=y.Cno; 17、 select y.cno,avg(y.degree) from student x,score y where x.sno=y.sno and x.class='95033'group by y.cno; 18、select Sno,Cno,rank from score,grade where degree between low and upp order by rank; 19、select distinct x.cno,x.sno,x.degree from score x,score y where x.cno = '3-105'
and x.degree > y.degree and y.sno='109' and y.cno='3-105'; 20、 1,查询成绩非本科最高 select distinct * from score b where degree <(select max(degree) from score a where a.cno=b.cno); 2,查询成绩非本科最高并且选2门以上的学生的成绩: 21、select x.cno,x.sno,x.degree from score x,score y where x.degree > y.degree and y.sno='109'and y.cno='3-105'; select cno,sno,degree from score where degree > (select degree from score where sno='109' and cno='3-105'); 22、 select sno,sname,sbirthday from student where to_char(sbirthday,'yyyy')
=(select to_char(sbirthday,'yyyy') from student where sno='108'); 23、select cno,sno,degree from score where cno=(select x.cno from course x,teacher y where x.tno=y.tno and y.tname='张旭'); 24、select tname from teacher where tno in(select x.tno from course x,score y where o group by x.tno having count(x.tno)>5); 25、select * from student where class in('95033','95031'); 26、select distinct cno from score where degree in (select degree from score where degree>85); 27、select * from score where cno in(select x.cno from course x,teacher y where y.tno=x.tno and y.depart='计算机系'); 28、select tname,prof from teacher where depart='计算机系' and prof not in (select prof from teacher where depart='电子工程系'); 29、select * from score where cno='3-105' and degree>any (select degree from score where cno='3-245')order by degree desc; 30、select * from score where cno='3-105' and degree>all(select degree from score where cno='3-245'); 31、select tname,tsex,tbirthday from teacher union select sname,ssex,sbirthday from student; 32、select tname,tsex,tbirthday from teacher where tsex='女' union select sname,ssex,sbirthday from student where ssex='女'; 33、select * from score a where degree<(select avg(degree) from score b where a.cno=b.cno); 34、select tname,depart from teacher a where exists (select * from course b where a.tno=b.tno); 35、select tname,depart from teacher a where not exists (select * from course b where a.tno=b.tno); 36、select class from student where ssex='男'group by class having count(*)>=2; 37、select * from student where sname not like'王_'; 38、select sname as 姓名,(to_char(sysdate,'yyyy')-to_char(sbirthday,'yyyy')) as 年龄 from student 39、select sname,sbirthday as 最大 from student where sbirthday =(select min (sbirthday)
from student)union select sname,sbirthday as 最小 from student where sbirthday =(select max(sbirthday) from student) 40、select class,sname,sbirthday from student order by class desc,sbirthday; 41、select x.tname,y.cname from teacher x,course y where x.tno=y.tno and x.tsex='男'; 42、select * from score where degree=(select max(degree)from score); 43、select sname from student where ssex=(select ssex from student where sname='李军'); 44、select sname from student where ssex=(select ssex from student where sname='李军')
and class=(select class from student where sname='李军'); 45、select * from score where sno in(select sno from student where ssex='男') and cno=(select cno from course where cname='计算机导论');
--创建表
USE test
CREATE TABLE emp
(
EMPNO NUMERIC(5, 0) NOT NULL ,
ENAME NVARCHAR(10) ,
JOB NVARCHAR(9) ,
MGR NUMERIC(5, 0) ,
HIREDATE DATETIME ,
SAL NUMERIC(7, 2) ,
COMM NUMERIC(7, 2) ,
DEPTNO NUMERIC(2, 0),
)
CREATE TABLE dept
(
DEPTNO NUMERIC(2) ,
DNAME NVARCHAR(14) ,
LOC NVARCHAR(13),
)
--插入数据
--1、查询所有的雇员
SELECT * FROM emp
--2、查询所有的部门
SELECT * FROM dept
--3、查询没有佣金(COMM)的所有雇员信息
SELECT * FROM dbo.emp WHERE COMM IS NULL
--4、查询薪金(SAL)和佣金(COMM)总数大于2000的所有雇员信息
SELECT * FROM emp WHERE ( sal + ISNULL(comm, 0) ) > 2000
--5、选择部门30中的雇员
SELECT * FROM emp WHERE deptno=30
--6、列出所有办事员("CLERK")的姓名、编号和部门
SELECT ename ,empno ,dname FROM emp JOIN dept ON emp.deptno = dept.deptnoWHERE emp.job = 'CLERK'
--7、找出佣金高于薪金的雇员
SELECT * FROM emp WHERE comm > sal
--8、找出佣金高于薪金60%的雇员
SELECT * FROM emp WHERE comm > sal * 0.6
--9、找出部门10中所有经理和部门20中的所有办事员的详细资料
SELECT * FROM emp WHERE ( job = 'MANAGER' AND deptno = 10) OR ( job = 'CLERK' AND deptno = 20) ORDER BY job
--10、找出部门10中所有经理、部门20中所有办事员,--既不是经理又不是办事员但其薪金>=2000的所有雇员的详细资料
SELECT * FROM dbo.emp WHERE ( JOB = 'MANAGER' AND DEPTNO = 10)OR ( JOB = 'CLERK' AND DEPTNO = 20) OR ( JOB NOT IN ( 'MANAGER', 'CLERK' ) AND SAL >= 2000) ORDER BY JOB
--11、找出收取佣金的雇员的不同工作
SELECT DISTINCT JOB FROM dbo.emp WHERE COMM IS NOT NULL
--12、找出不收取佣金或收取的佣金低于100的雇员
SELECT * FROM emp WHERE ISNULL(comm, 0) < 100
--13、找出早于12年之前受雇的雇员
SELECT * FROM dbo.emp WHERE YEAR(GETDATE()) - YEAR(HIREDATE) > 11
--14、显示首字母大写的所有雇员的姓名
SELECT ename FROM emp WHERE ASCII(ename) BETWEEN 65 AND 90
--15、显示正好为5个字符的雇员姓名
SELECT ename FROM emp WHERE LEN(ename) = 5
--16、显示带有'R'的雇员姓名
SELECT ENAME FROM dbo.emp WHERE ENAME LIKE '%R%''
--17、显示不带有'R'的雇员姓名
SELECT ENAME FROM dbo.emp WHERE ENAME NOT LIKE '%R%'
--18、显示包含"A"的所有雇员的姓名及"A"在姓名字段中的位置
SELECT ENAME ,CHARINDEX('A', ENAME) A的位置 FROM dbo.emp WHERE ENAME LIKE '%A%'
--19、显示所有雇员的姓名,用a替换所有'A'
SELECT REPLACE(ename, 'A', 'a') ENAME FROM dbo.emp
--20、显示所有雇员的姓名的前三个字符
SELECT SUBSTRING(ename, 1, 3) ENAME FROM dbo.emp
--21、显示雇员的详细资料,按姓名排序
SELECT * FROM dbo.emp ORDER BY ENAME
--22、显示雇员姓名,根据其服务年限,将最老的雇员排在最前面
SELECT ENAME FROM dbo.emp ORDER BY HIREDATE
--23、显示所有雇员的姓名、工作和薪金,按工作内的工作的降序顺序排序,
--而工作按薪金排序
SELECT ename , job ,sal FROM emp ORDER BY job DESC ,Sal
--24、显示在一个月为30天的情况下所有雇员的日薪金,忽略小数
SELECT ename 名字 ,CAST(sal / 30 AS NUMERIC) 日薪 FROM dbo.emp
--25、找出在(任何年份的)2月受聘的所有雇员
SELECT ename ,hiredate FROM dbo.emp WHERE MONTH(hiredate) = 2
--26、对于每个雇员,显示其加入公司的天数
SELECT ename 姓名 ,DATEDIFF(DAY, hiredate, GETDATE()) 天数 FROM dbo.emp
--27、列出至少有一个雇员的所有部门
SELECT * FROM dbo.dept WHERE DEPTNO IN ( SELECT DEPTNO FROM dbo.emp )
--28、列出各种类别工作的最低薪金
SELECT job ,MIN(sal) minsal FROM dbo.emp GROUP BY job
--29、列出各个部门的MANAGER(经理)的最低薪金
SELECT ename ,dname ,MIN(sal) minsal FROM dbo.emp ,dbo.dept WHERE emp.deptno = dept.deptno AND job = 'MANAGER' GROUP BY dname ,ename
--30、列出薪金高于公司平均水平的所有雇员
SELECT ename ,sal FROM dbo.emp WHERE sal > ( SELECT AVG(sal)FROM dbo.emp)
--31、列出各种工作类别的最低薪金,并使最低薪金大于1500
SELECT job ,MIN(sal) minsal FROM dbo.emp GROUP BY job HAVING MIN(sal) > 1500
--32、显示所有雇员的姓名和加入公司的年份和月份,
--按雇员受雇日所在月排序,将最早年份的项目排在最前面
SELECT ename ,YEAR(hiredate) _year ,MONTH(hiredate) _month FROM emp ORDER BY hiredate
--33、显示所有雇员的姓名以及满10年服务年限的日期
SELECT ename ,hiredate FROM emp WHERE DATEDIFF(YEAR, hiredate, GETDATE()) > 10
--34、显示所有雇员的服务年限:总的年数或总的月数或总的天数
SELECT ename ,DATEDIFF(YEAR, hiredate, GETDATE()) _years ,DATEDIFF(MONTH, hiredate, GETDATE()) _months ,DATEDIFF(DAY, hiredate, GETDATE()) _days FROM dbo.emp
--35、列出按计算的字段排序的所有雇员的年薪.
--即:按照年薪对雇员进行排序,年薪指雇员每月的总收入总共12个月的累加
SELECT ename , CAST(sal + ISNULL(comm, 0) AS NUMERIC) * 12 sal_year FROM dbo.emp
ORDER BY sal_year
--36、列出年薪前5名的雇员
SELECT TOP 5 ename ,CAST(sal + ISNULL(comm, 0) AS NUMERIC) * 12 sal_year FROM dbo.emp
ORDER BY sal_year DESC
--列出薪金水平处于第四位的雇员
--注意子查询一定要起别名
SELECT * FROM ( SELECT ename ,sal ,rank() OVER ( ORDER BY sal DESC ) AS grade
FROM emp) AS a WHERE a.grade = 4
--37、列出年薪低于10000的雇员
SELECT * FROM dbo.emp WHERE ( sal + ISNULL(comm, 0) ) * 12 < 10000
--38、列出雇员的平均月薪和平均年薪
SELECT CAST(SUM(sal + ISNULL(comm, 0)) / COUNT(ename) AS NUMERIC) 平均月薪 ,CAST(SUM(( sal + ISNULL(comm, 0) ) * 12) / COUNT(ename) AS NUMERIC) 平均年薪 FROM emp
--39、列出部门名称和这些部门的雇员,同时列出那些没有雇员的部门(重要)
SELECT dname ,ename FROM dept LEFT JOIN emp ON emp.deptno = dept.deptno ORDER BY dname
--列出那些没有雇员的部门
SELECT dname FROM emp RIGHT JOIN dept ON emp.deptno = dept.deptno WHERE emp.ename IS NULL
--40、列出每个部门的信息以及该部门中雇员的数量(重要)
SELECT dept.*,COUNT(emp.ENAME) 人数 FROM dept LEFT JOIN dbo.emp ON dbo.dept.DEPTNO = dbo.emp.DEPTNO GROUP BY dept.DNAME,dept.DEPTNO,dept.LOC ORDER BY dbo.dept.DEPTNO
--41、列出薪金比"SMITH"多的所有雇员
SELECT emp.ename ,emp.sal FROM emp WHERE sal > ( SELECT sal FROM emp WHERE ename = 'smith')
--42、列出所有雇员的姓名及其直接上级的姓名
SELECT A.ENAME 雇员 ,B.ENAME 直接上级 FROM dbo.emp A LEFT JOIN dbo.emp B ON A.MGR = B.EMPNO
ORDER BY B.EMPNO
--43、列出入职日期早于其直接上级的所有雇员
SELECT ename 雇员 ,hiredate 雇员入职日期 FROM emp e WHERE hiredate < ( SELECT hiredate
FROM emp WHERE empno = e.mgr)
--44、列出所有办事员("CLERK")的姓名及其部门名称
SELECT ename ,dname ,job FROM emp e JOIN dept d ON e.deptno = d.deptno WHERE job = 'CLERK'
--45、列出从事"SALES"(销售)工作的雇员的姓名,假定不知道销售部的部门编号
SELECT ename FROM emp WHERE deptno = ( SELECT deptno FROM dept WHERE dname = 'sales')
--46、列出与"SCOTT"从事相同工作的所有雇员
SELECT ename ,job FROM emp WHERE job = ( SELECT job FROM emp WHERE ename = 'SCOTT')
--47、列出某些雇员的姓名和薪金,条件是他们的薪金等于部门30中任何一个雇员的薪金
SELECT ename ,sal ,deptno FROM emp WHERE sal IN ( SELECT sal FROM emp WHERE deptno = 30 )
--48、列出某些雇员的姓名和薪金,条件是他们的薪金高于部门30中所有雇员的薪金
SELECT ename ,sal ,deptno FROM emp WHERE sal >( SELECT MAX(sal) FROM emp WHERE deptno = 30)
--49、列出从事同一种工作但属于不同部门的雇员的不同组合
SELECT a.ename 雇员A ,b.ename 雇员B ,a.job 雇员A工作 , b.job 雇员B工作 ,a.deptno 雇员A部门 ,b.deptno 雇员B部门 FROM emp a JOIN emp b ON a.job = b.job WHERE a.deptno != b.deptno
AND a.job = b.job ORDER BY a.job
--50、列出所有雇员的雇员名称、部门名称和薪金(包括没有雇员的部门)
SELECT dbo.dept.DNAME ,dbo.emp.ENAME ,dbo.emp.SAL FROM dbo.empRIGHT JOIN dbo.dept ON dbo.dept.DEPTNO = dbo.emp.DEPTNO
第一方面:
30种mysql优化sql语句查询的方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20 可以这样查询: select id from t where num=10 union all select id from t where num=20 5.下面的查询也将导致全表扫描: select id from t where name like '%abc%' 若要提高效率,可以考虑全文检索。 6.in 和 not in 也要慎用,否则会导致全表扫描,如: select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了: select id from t where num between 1 and 3 7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t where num=@num 可以改为强制查询使用索引: select id from t with(index(索引名)) where num=@num 8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where num/2=100 应改为: select id from t where num=100*2 9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where substring(name,1,3)='abc'--name以abc开头的id select id from t where datediff(day,createdate,'2005-11-30')=0--'2005-11-30'生成的id 应改为: select id from t where name like 'abc%' select id from t where createdate>='2005-11-30' and createdate<'2005-12-1' 10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。 12.不要写一些没有意义的查询,如需要生成一个空表结构: select col1,col2 into #t from t where 1=0 这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样: create table #t(...) 13.很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num) 14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。 15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。 16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。 17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。 18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。 19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。 20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。 21.避免频繁创建和删除临时表,以减少系统表资源的消耗。 22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。 23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。 24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。 25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。 26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。 27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。 28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。 29.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。 30.尽量避免大事务操作,提高系统并发能力。
第二方面:
select Count (*)和Select Count(1)以及Select Count(column)区别
一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的
假如表沒有主键(Primary key), 那么count(1)比count(*)快,
如果有主键的話,那主键作为count的条件时候count(主键)最快
如果你的表只有一个字段的话那count(*)就是最快的
count(*) 跟 count(1) 的结果一样,都包括对NULL的统计,而count(column) 是不包括NULL的统计
第三方面:
索引列上计算引起的索引失效及优化措施以及注意事项
创建索引、优化查询以便达到更好的查询优化效果。但实际上,MySQL有时并不按我们设计的那样执行查询。MySQL是根据统计信息来生成执行计划的,这就涉及索引及索引的刷选率,表数据量,还有一些额外的因素。
Each table index is queried, and the best index is used unless the optimizer believes that it is more efficient to use a table scan. At one time, a scan was used based on whether the best index spanned more than 30% of the table, but a fixed percentage no longer determines the choice between using an index or a scan. The optimizer now is more complex and bases its estimate on additional factors such as table size, number of rows, and I/O block size.
简而言之,当MYSQL认为符合条件的记录在30%以上,它就不会再使用索引,因为mysql认为走索引的代价比不用索引代价大,所以优化器选择了自己认为代价最小的方式。事实也的确如此
是MYSQL认为记录是30%以上,而不是实际MYSQL去查完再决定的。都查完了,还用什么索引啊?!
MYSQL会先估算,然后决定是否使用索引。