本文共 7688 字,大约阅读时间需要 25 分钟。
在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了上面这样一个功能。
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
mysql> SELECT * FROM table LIMIT 5,10; //检索记录行6-15
//为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last. //如果只给定一个参数,它表示返回最大的记录行数目: mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行//换句话说,LIMIT n 等价于 LIMIT 0,n。
由于 SQLite 中没有直接统计字符串中子串出现次数的函数,因此本题用length()函数与replace()函数的结合灵活地解决了统计子串出现次数的问题,属于技巧题,即先用replace函数将原串中出现的子串用空串替换,再用原串长度减去替换后字符串的长度,最后除以子串的长度(本题中此步可省略,若子串长度大于1则不可省)。
SELECT (length("10,A,B")-length(replace("10,A,B",",","")))/length(",") AS cnt
还可以利用OJ系统的Bug直接输出2次来通过测试
SELECT 2 AS cnt
replace函数的用法:
replace('A','b','c') 用c替换字符串A中所有的b
select first_name
from employees
order by substr(first_name,-2)
select first_name
from employees
order by substr(first_name,length(first_name)-1,length(first_name))
本题要用到SQLite的聚合函数group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。此函数必须与 GROUP BY 配合使用。此题以 dept_no 作为分组,将每个分组中不同的emp_no用逗号连接起来(即可省略Y)。
SELECT dept_no, group_concat(emp_no) AS employees
FROM dept_emp GROUP BY dept_no
select avg(salary) as avg_salary
from salaries
where salary not in
(select max(salary) from salaries
union
select min(salary) from salaries)
and to_date='9999-01-01'
根据题意,不能使用 INTERSECT 关键字,但由于视图 emp_v 的记录是从 employees 中导出的,因此要判断两者中相等的数据,只需要判断emp_no相等即可。
方法一:用 WHERE 选取二者 emp_no 相等的记录
SELECT em.* FROM employees AS em, emp_v AS ev WHERE em.emp_no = ev.emp_no
方法二:由于emp_v的全部记录均由 employees 导出,因此可以投机取巧,直接输出 emp_v 所有记录
SELECT * FROM emp_v
select * from employees order by hire_date desc limit 0,1
查找入职员工时间排名倒数第三的员工所有信息
select * from employees order by hire_date desc limit 2,1
select s1.emp_no,s1.salary,(select sum(s2.salary) from salaries s2 where s1.emp_no >=s2.emp_no
and s2.to_date='9999-01-01' )
as running_total
from salaries s1
where s1.to_date='9999-01-01'
order by s1.emp_no
select d.emp_no, dm.emp_no as manager_no
from dept_emp d ,dept_manager dm
where d.to_date='9999-01-01'
and dm.to_date='9999-01-01'
and d.dept_no=dm.dept_no
and d.emp_no !=dm.emp_no
select s.emp_no,max(s.salary),e.last_name,e.first_name
from employees e ,salaries s
where e.emp_no=s.emp_no
and s.to_date='9999-01-01'
and s.salary < (select max(salary) from salaries)
select salaries.*,dept_manager.dept_no from salaries,dept_manager
where salaries.emp_no = dept_manager.emp_no
and salaries.to_date='9999-01-01'
and dept_manager.to_date = '9999-01-01'
select e.emp_no,s.salary
from employees e,salaries s
where e.emp_no=s.emp_no
and e.hire_date=s.from_date ################重要
order by s.emp_no desc
解析:由于有些员工可能没有分配部门号,需要用左外连接就好了,即返回左表中所有的行,即便右表没有满足的条件
select a.last_name,a.first_name,b.dept_no from employees a left join dept_emp b on a.emp_no=b.emp_no
本题主要思想是创建两张表(一张记录当前所有员工的工资,另一张只记录部门经理的工资)进行比较,具体思路如下:
1、先用INNER JOIN连接salaries和demp_emp,建立当前所有员工的工资记录sem
2、再用INNER JOIN连接salaries和demp_manager,建立当前所有员工的工资记录sdm
3、最后用限制条件sem.dept_no = sdm.dept_no AND sem.salary > sdm.salary找出同一部门中工资比经理高的员工,并根据题意依次输出emp_no、manager_no、emp_salary、manager_salary
select sem.emp_no as emp_no,sdm.emp_no as manager_no,sem.salary as emp_salary,sdm.salary as manager_salary
from
(select s.emp_no,s.salary,de.dept_no from salaries s ,dept_emp de where s.emp_no=de.emp_no
and s.to_date='9999-01-01')
as sem,
(select s.emp_no,s.salary,dm.dept_no from salaries s ,dept_manager dm where s.emp_no=dm.emp_no
and s.to_date='9999-01-01')
as sdm
where sem.dept_no=sdm.dept_no
and sem.salary >sdm.salary
select e.last_name,e.first_name,d.dept_no
from employees e,dept_emp d
where e.emp_no = d.emp_no
select emp_no,count(emp_no) as t
from salaries s
group by emp_no having t >15
select distinct salary
from salaries
where to_date='9999-01-01'
order by salary desc
#### disticit
select e.emp_no
from employees e
where e.emp_no not in (select d.emp_no from dept_manager d )
select d.dept_no,s.emp_no ,max(s.salary) as salary
from dept_emp d ,salaries s
where d.emp_no=s.emp_no
and d.to_date='9999-01-01'
and s.to_date='9999-01-01'
group by d.dept_no
select t.title,avg(s.salary) as avg
from salaries s ,titles t
where s.emp_no = t.emp_no
and s.to_date='9999-01-01'
and s.to_date=t.to_date
group by t.title
select e.last_name,e.first_name,d.dept_name
from employees e
left join dept_emp de
on e.emp_no =de.emp_no
left join departments d
on d.dept_no=de.dept_no
select e.emp_no,(s.salary-ss.salary) as growth
from employees e,salaries s,salaries ss
where e.emp_no=s.emp_no
and e.emp_no=ss.emp_no
and s.to_date='9999-01-01'
and ss.from_date=e.hire_date
order by growth asc
select d.dept_no,d.dept_name,count(salary)as sum
from departments d,dept_emp de,salaries s
where d.dept_no=de.dept_no
and de.emp_no=s.emp_no
group by d.dept_no
select title, count(distinct emp_no) as t
from titles
group by title having t>=2
输出描述:
title | t |
Assistant Engineer | 2 |
Engineer | 3 |
省略 | 省略 |
Staff | 3 |
对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照emp_no升序排列
select s1.emp_no,s1.salary, count(distinct s2.salary) as rank
from salaries s1 ,salaries s2
where s1.to_date='9999-01-01'
and s2.to_date='9999-01-01'
and s1.salary <=s2.salary
group by s1.emp_no
order by s1.salary desc ,s1.emp_no asc
select s.emp_no,e.first_name,e.last_name,eb.btype,s.salary,(
case eb.btype
when 1 then s.salary*0.1
when 2 then s.salary*0.2
else s.salary*0.3 end) as bonus
from salaries s inner join emp_bonus eb on s.emp_no= eb.emp_no
inner join employees e on s.emp_no=e.emp_no
and s.to_date='9999-01-01'
其实观察测试数据会发现 btype 只有1,2,3三种情况,即使不会 CASE 表达式,也能运用四则运算解出:(注意要除以10.0,如果除以10的话,结果的小数位会被舍去)
SELECT e.emp_no, e.first_name, e.last_name, b.btype, s.salary,
(s.salary * b.btype / 10.0) AS bonus
FROM employees AS e INNER JOIN emp_bonus AS b ON e.emp_no = b.emp_no
INNER JOIN salaries AS s ON e.emp_no = s.emp_no AND s.to_date = '9999-01-01'
转载地址:http://qftgn.baihongyu.com/