2016-09-13 22 views
1

所以我有这些表:SQL Server的支点查询替代或优化

-- tbl_obs 
id lat lon created 
------------------------- 
1 1.2 -2.1 2002-08-03 
2 1.9 -5.5 2002-08-03 
3 1.5 -4.1 2002-08-03 

-- tbl_obsdata 
id name   value  obs_id 
--------------------------------- 
1 gender  Male  1 
2 type   Type I  1 
3 description Some desc 1 
4 gender  Female  2 
5 type   Type II 2 
6 description Some desc 2 
7 gender  Female  3 
8 type   Type II 3 
9 description Some desc 3 

我想要一个查询,将来自两个表这样的数据组合:

lat lon created  gender type description 
------------------------------------------------ 
1.2 -2.1 2002-08-03 Male Type I Some desc 
1.9 -5.5 2002-08-03 Female Type I Some desc 
1.5 -4.1 2002-08-03 Male Type II Some desc 

我知道我能做到这一点与像一个支点:

with cte as (
select obsdata.name, obsdata.value, obs.lat, obs.lon, obs.created 
from obsdata 
left join obs on obs.id = obsdata.obs_id 
) 
select lat, lon, created, gender, type, description 
from cte 
pivot(
max(value) 
for [name] in (gender, type, description) 
) as pvt 

到目前为止,返回结果(我认为),但我有一百万行,这个运行非常缓慢。任何替代方法来实现这将更快?我正在使用SQL Server 2012.

回答

4

另一种选择是

Select A.lat 
     ,A.lon 
     ,A.created 
     ,gender  = max(IIF(B.name='gender',B.value,null)) 
     ,type  = max(IIF(B.name='type',B.value,null)) 
     ,description = max(IIF(B.name='description',B.value,null)) 
From tbl_obs A 
Join tbl_obsdata B on (A.id=B.obs_id) 
Group By A.lat 
     ,A.lon 
     ,A.created 

返回

lat lon  created  gender type description 
1.2 -2.1 2002-08-03 Male Type I Some desc 
1.5 -4.1 2002-08-03 Female Type II Some desc 
1.9 -5.5 2002-08-03 Female Type II Some desc 
3

优化首先,然后join。我认为,SQL Server会为支点合理的工作,所以开始:

select obs_id, gender, type, description 
from tbl_obsdata 
pivot (max(value) for [name] in (gender, type, description) 
    ) as pvt; 

然后,在tbl_obsdata(obs_id, name, value)创建索引。这应该是相当快的。

如果是这样,那么加入其余:

with cte as (
     select obs_id, gender, type, description 
     from tbl_obsdata 
     pivot (max(value) for [name] in (gender, type, description) 
      ) as pvt 
    ) 
select obs.lat, obs.lon, obs.created, 
     cte.gender, cte.type, cte.description 
from cte join 
    obs 
    on obs.id = cte.obs_id; 

编辑:

我还纳闷怎么这会票价:

select obs.lat, obs.lon, obs.created, od.gender, od.type, od.description 
from obs cross apply 
    (select max(case when name = 'gender' then value end) as gender, 
      max(case when name = 'type' then value end) as type, 
      max(case when name = 'description' then value end) as description 

     from tbl_obsdata od 
     where od.obs_id = obs.id 
    ) od; 

这希望就tbl_obsdata(obs_id, name, value)指数为好。

+0

现在它看上去很美。通过查看这个问题,我认为CTE可能是缓慢的原因。你会喜欢临时表(带索引)而不是CTE吗? – BhatiaAshish

+0

@BhatiaAshish。 。 。我更喜欢对临时表进行单个查询,除非后者是绝对必要的。 –

+2

枢轴有性能问题,通常会比John Cappalletti在这里给出的解决方案慢。 Unpivots很好,但由于我在高容量的大数据环境中工作,我从不使用枢轴。 – btberry