2016-09-13 16 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; 

EDIT:

私もこれは運賃だろうか疑問に思う:

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などのソリューションよりも遅くなります。ピボットはうまくありませんが、大容量の大容量データ環境で作業しているのでピボットは使用しません。 – btberry

関連する問題