2016-09-13 2 views
1

Поэтому у меня есть эти таблицы:SQL альтернативный стержень сервера запросов или оптимизации

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

У Pivots есть проблемы с производительностью и, как правило, будет медленнее, чем такие решения, как, например, Джон Каппалетти. Unpivots прекрасны, но поскольку я работаю в среде с большими объемами больших объемов данных, я никогда не использую опорные точки. – btberry

Смежные вопросы