SQL Server创建两个表并进行比较

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

我在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-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