如题所示 ,下面是表结构
[email protected]>[employees]>desc dept_emp;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| dept_no | char(4) | NO | PRI | NULL | |
| from_date | date | NO | | NULL | |
| to_date | date | NO | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
从上面的表结构中 求出满足以下条件
从1985-01-01 到1985-02-28 部门每个部门每天的在职人数
我们想求出满足上面的人 ,from_date 必须小于 2018-02-08 而to_date 必须大于等于 2018-01-01
select dept_no , emp_no ,d.from_date,d.to_date from dept_emp d
where d.from_date <= '1985-02-08'
and d.to_date >= '1985-01-01'
从查询结果中 可以看出
| d008 | 429002 | 1985-02-20 | 9999-01-01 |
如上图所示 429002 在2-20进入部门d008 现在还在职 就一行数据
我们都知道 聚合函数是对表的行进行计算的 如果想用聚合函数 我们就得复制
如下才行
| d008 | 429002 | 1985-02-20 | 9999-01-01 |
| d008 | 429002 | 1985-02-21 | 9999-01-01 |
| d008 | 429002 | 1985-02-22 | 9999-01-01 |
这样我们 才计算出 20号一天 ,21号一天 22号1天 但现实就是一行数据
这时候 我们需要一个特殊的表!
create table t_time (
id int primary key auto_increment ,
yymmdd date
)
insert into t_time(yymmdd) values('1985-01-01');
insert into t_time(yymmdd)
select adddate('1985-01-01',INTERVAL rn day)
from (
select @a:=@a+1 rn from (select * from dept_emp limit 10000) a ,(select @a:=0) b
)c
通过上面的脚本 可以创建一个表 包含从85-01-01到12年的日期!
select dept_no,t.yymmdd , emp_no ,d.from_date, d.to_date from dept_emp d , t_time t
where d.from_date <= t.yymmdd
and d.to_date >= t.yymmdd
and t.yymmdd <='1985-02-28'
order by 1 ,3 ,2
| d009 | 1985-02-28 | 489879 | 1985-02-07 | 9999-01-01 |
| d009 | 1985-02-18 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-19 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-20 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-21 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-22 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-23 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-24 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-25 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-26 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-27 | 499222 | 1985-02-18 | 1996-07-07 |
| d009 | 1985-02-28 | 499222 | 1985-02-18 | 1996-07-07 |
+---------+------------+--------+------------+------------+
这样 我们就很好的进行了复制
然后运行如下! 就可以求出 每个部门每个月的在职人数
select dept_no,date_format(t.yymmdd,'%Y%m') , count(distinct emp_no) from dept_emp d , t_time t
where d.from_date <= t.yymmdd
and d.to_date >= t.yymmdd
and t.yymmdd <='1985-02-28'
group by dept_no,date_format(t.yymmdd,'%Y%m')
+---------+------------------------------+------------------------+
| dept_no | date_format(t.yymmdd,'%Y%m') | count(distinct emp_no) |
+---------+------------------------------+------------------------+
| d001 | 198501 | 1 |
| d001 | 198502 | 86 |
| d002 | 198501 | 2 |
| d002 | 198502 | 83 |
| d003 | 198501 | 1 |
| d003 | 198502 | 76 |
| d004 | 198501 | 1 |
| d004 | 198502 | 335 |
| d005 | 198501 | 1 |
| d005 | 198502 | 450 |
| d006 | 198501 | 1 |
| d006 | 198502 | 70 |
| d007 | 198501 | 1 |
| d007 | 198502 | 235 |
| d008 | 198501 | 1 |
| d008 | 198502 | 93 |
| d009 | 198501 | 1 |
| d009 | 198502 | 92 |
+---------+------------------------------+------------------------+
测试
select count(*) from dept_emp where from_date<='1985-02-28'
and to_date>='1985-02-01' and dept_no = 'd008'
+----------+
| count(*) |
+----------+
| 93 |
+----------+
select dept_no,date_format(t.yymmdd,'%Y%m') , count(distinct emp_no) from dept_emp d , t_time t
where d.from_date <= t.yymmdd
and d.to_date >= t.yymmdd
and t.yymmdd <='1985-02-28'
and dept_no = 'd008'
group by dept_no,date_format(t.yymmdd,'%Y%m')
---------+------------------------------+------------------------+
| dept_no | date_format(t.yymmdd,'%Y%m') | count(distinct emp_no) |
+---------+------------------------------+------------------------+
| d008 | 198501 | 1 |
| d008 | 198502 | 93 |
+---------+------------------------------+------------------------+
从结果上可以看出 我们计算的是正确的!