SQL Server创建两个表并进行比较
我在SQL Server 2012中有一个包含3列的表。其中一列是日期列。我想做的是将表拆分为两个指定日期,并将它们合并到一个带有额外字段的表中。希望下面的例子能够解释 我目前拥有的示例SQL Server创建两个表并进行比较,sql,sql-server,Sql,Sql Server,我在SQL Server 2012中有一个包含3列的表。其中一列是日期列。我想做的是将表拆分为两个指定日期,并将它们合并到一个带有额外字段的表中。希望下面的例子能够解释 我目前拥有的示例 Company date no_employees ABC 2014-05-30 35 DEF 2014-05-30 322 GHI 2014-05-30 65 JKL 2014-05-30 8 MNO 2014-0
Company date no_employees
ABC 2014-05-30 35
DEF 2014-05-30 322
GHI 2014-05-30 65
JKL 2014-05-30 8
MNO 2014-05-30 30
ABC 2014-01-01 33
DEF 2014-01-01 301
GHI 2014-01-01 70
MNO 2014-01-01 30
我希望查询返回的内容不确定是否可能
Company start date no_employees end date no_employees diff
ABC 33 35 2
DEF 301 322 21
GHI 70 65 -5
JKL 0 8 8
MNO 30 30 0
生成0似乎就是这样:
declare @t table (Company char(3),[date] date,no_employees int)
insert into @t(Company,[date],no_employees) values
('ABC','2014-05-30',35 ),
('DEF','2014-05-30',322 ),
('GHI','2014-05-30',65 ),
('JKL','2014-05-30',8 ),
('MNO','2014-05-30',30 ),
('ABC','2014-01-01',33 ),
('DEF','2014-01-01',301 ),
('GHI','2014-01-01',70 ),
('MNO','2014-01-01',30 )
select Company,
COALESCE(start,0) as start,
COALESCE([end],0) as [end],
COALESCE([end],0)-COALESCE(start,0) as diff
from
(select
Company,
CASE WHEN [date]='20140530' THEN 'end'
ELSE 'start' END as period,
no_employees
from @t
where [date] in ('20140101','20140530')
) t
pivot (MAX(no_employees) for period in ([start],[end])) u
结果:
Company start end diff
------- ----------- ----------- -----------
ABC 33 35 2
DEF 301 322 21
GHI 70 65 -5
JKL 0 8 8
MNO 30 30 0
对于要使用的特定开始和结束日期,可以很容易地对其进行参数化
此外,目前我使用MAX,因为我们必须在PIVOT中有一个聚合,即使这里的示例数据最多包含一行。如果开始日期或结束日期可能存在多行,我们需要知道您希望如何处理这些行。选择公司。外部连接开始日期记录。外部连接结束日期记录。使用coalesce显示0而不是null
declare @t table (Company char(3),[date] date,no_employees int)
insert into @t(Company,[date],no_employees) values
('ABC','2014-05-30',35 ),
('DEF','2014-05-30',322 ),
('GHI','2014-05-30',65 ),
('JKL','2014-05-30',8 ),
('MNO','2014-05-30',30 ),
('ABC','2014-01-01',33 ),
('DEF','2014-01-01',301 ),
('GHI','2014-01-01',70 ),
('MNO','2014-01-01',30 )
select Company,MIN(no_employees),MAX(no_employees),CASE WHEN MIN(no_employees) = MAX(no_employees) then MAX(no_employees) else
MIN(no_employees) - MAX(no_employees) end as cNT from @t
GROUP BY Company
select
company,
coalesce(rec20140101.no_employees, 0) as empno_start,
coalesce(rec20140530.no_employees, 0) as empno_end
from
(
select distinct company
from records
) companies -- or use a company table if you have one
left join
(
select company, no_employees
from records
where recorddate = '2014-01-01'
) rec20140101
on rec20140101.company = companies.companyrec
left join
(
select company, no_employees
from records
where recorddate = '2014-05-30'
) rec20140530
on rec20140530.company = companies.company);
编辑:这里有一种只扫描表一次的方法。它甚至有点短-
select
company,
coalesce(min( case when recorddate = '2014-05-30' then no_employees end ), 0) as empno_start,
coalesce(min( case when recorddate = '2014-01-01' then no_employees end ), 0) as empno_end
from records
group by company;
试试这个:
;with cte as
(select
COALESCE(src.company, tgt.company) company
isnull(tgt.no_employees,0) 'start date no_employees',
isnull(src.no_employees , 0) 'end date no_employees'
from
tbl src
full outer join tbl tgt on src.company = tgt.company and src.date <> tgt.date
where (src.date = (select max(date) from tbl) or src.date is null)
and (tgt.date = (select min(date) from tbl) or tgt.date is null)
)
select *, [end date no_employees] - [start date no_employees] diff
from cte
仅使用最小值和最大值是不正确的,因为GHI行的值为70,65,出现在这两列中。此外,您的cNT列看起来很难生成任何不等于最大值的非负值。只有两行可以生成所需的结果。每个日期最多只能有一个公司,所以相信MAX应该可以。正准备尝试。+1似乎其他大多数建议都有一个共同点。他们缺少完全连接。Pivot在该限制下不受影响。
;with cte as
(select
COALESCE(src.company, tgt.company) company
isnull(tgt.no_employees,0) 'start date no_employees',
isnull(src.no_employees , 0) 'end date no_employees'
from
tbl src
full outer join tbl tgt on src.company = tgt.company and src.date <> tgt.date
where (src.date = (select max(date) from tbl) or src.date is null)
and (tgt.date = (select min(date) from tbl) or tgt.date is null)
)
select *, [end date no_employees] - [start date no_employees] diff
from cte
declare @lowdate date = '2014-01-01'
declare @highdate date = '2014-05-30'
;with x as
(
select company, min(no_employees) no_employees
from @t records
where recorddate = @lowdate
group by company
), y as
(
select company, max(no_employees) no_employees
from @t records
where recorddate = @highdate
group by company
)
select coalesce(x.company, y.company) company,
coalesce(x.no_employees, 0) start_no_employees,
coalesce(y.no_employees, 0) end_no_employees,
coalesce(y.no_employees, 0) - coalesce(x.no_employees, 0) diff
from
x full outer join y
on
x.company = y.company