Нужна серьезная помощь с проблемой Self Join
Вопрос
Что ж, как вы можете знать, вы не можете индексировать вид с Self Injoin. Ну, на самом деле даже два присоединения того же стола, даже если это не технически самостоятельно присоединиться. Пара парней из Microsoft придумала оборота. Но это так сложно, я не понимаю это !!!
Решение проблемы входит здесь: http://jmkehayias.blogspot.com/2008/12/Creating-indexed-view-with-sels-soin.html.
Вид, который я хочу применить эту работу вокруг:
create VIEW vw_lookup_test
WITH SCHEMABINDING
AS
select
count_big(*) as [count_all],
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm [owner],
t.circt_cstdn_nm [tech],
dvc.circt_nm,
data_orgtn_yr
from
((dbo.dvc
join dbo.circt
on dvc.circt_nm = circt.circt_nm)
join dbo.circt_cstdn o
on circt.circt_cstdn_user_id = o.circt_cstdn_user_id)
join dbo.circt_cstdn t
on dvc.circt_cstdn_user_id = t.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm,
t.circt_cstdn_nm,
dvc.circt_nm,
data_orgtn_yr
go
Любая помощь была бы очень церован !!!
Большое спасибо заранее!
Редактировать: Итак, я обнаружил, что это также будет работать. Обратите внимание, что я присоединяюсь к таблице один раз в первом проиндексированном виде, а второй раз в втором неиндексированном представлении.
alter VIEW vw_lookup_owner_test2
WITH SCHEMABINDING
AS
select
count_big(*) as [countAll],
awc_txt,
city_nm,
str_nm,
stru_no,
dvc.circt_nm,
circt_cstdn_nm,
data_orgtn_yr,
dvc.circt_cstdn_user_id
from dbo.dvc
join dbo.circt
on dvc.circt_nm = circt.circt_nm
join dbo.circt_cstdn o
on circt.circt_cstdn_user_id = o.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
dvc.circt_nm,
circt_cstdn_nm,
data_orgtn_yr,
dvc.circt_cstdn_user_id
go
и
CREATE UNIQUE CLUSTERED INDEX [idx_vw_lookup_owner2_test1] ON [dbo].[vw_lookup_owner_test2]
(
[awc_txt] ASC,
[city_nm] ASC,
[str_nm] ASC,
[stru_no] ASC,
[circt_nm] ASC,
[circt_cstdn_nm] ASC,
[data_orgtn_yr] ASC,
[circt_cstdn_user_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
и
create view vw_lookup_dvc_loc
as
select
awc_txt,
city_nm,
str_nm,
stru_no,
circt_nm,
o.circt_cstdn_nm as [owner],
--o.circt_cstdn_user_id,
t.circt_cstdn_nm as tech,
data_orgtn_yr
from vw_lookup_owner_test2 o With (NOEXPAND)
join circt_cstdn t
on o.circt_cstdn_user_id = t.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
circt_nm,
o.circt_cstdn_nm,
data_orgtn_yr,
t.circt_cstdn_nm
--o.circt_cstdn_user_id
Затем я могу создать индексы Additon на первом представлении, как я желаю. Я не уверен, что это решение (или обходной путь в этом отношении) фактически ускоряет преформацию, но я дам вам знать.
Решение
Вот что я получил от blogpost
Допустим, вы хотите присоединиться к 2 раза на dbo.circt_cstdn, то есть вы хотите что-то вроде
owner tech rowA a.nm b.nm ...
Вместо того, чтобы получить значения в 2 столбца, вы получаете его на 2 строки (2 для каждой строки выше) и добавьте дополнительный столбец, чтобы сказать, какая строка предназначена для какой столбец. Обратите внимание, что строка 1.1 и строка 1.2 имеют те же данные (кроме имени и для столбцов)
name for row1.1 nm owner row1.2 nm tech ...
Тогда вы поворачиваете на максимум имени столбец для владельца и техники. ПРИМЕЧАНИЕ. - Максимальная функция - просто чтобы обмануть пивот (которая требует некоторой совокупной функции), вы можете использовать любую совокупную функцию, которая возвращает одинаковое значение, если есть только одна запись владельца Tech Row1 NM NM ...
Теперь, если мы сделаем это для вашего запроса
Создать таблицу D, как этот
i 1 2
Крест Присоединяйтесь к первой части вашего запроса с этим
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, d.i
Теперь давайте будем использовать ряд для владельца, если di 1, а Tech If Di 2
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END
Теперь добавьте столбец NM. Чтобы получить имя, которое вы присоединитесь к CIRCT_CSTDN с CIRCT, если это ряд владельца (di = 1), а с dvc, если это технологический ряд (di = 2). ПРИМЕЧАНИЕ - я попробовал здесь ярлык, положив это в состояние соединения. Если это не сработает, попробуйте просмотреть блог Путь (сделайте соединение на CIRCT.CIRCT_CSTDN_USER_ID ИЛИ dvc.circt_cstdn_user_id, а затем используйте предложение, где можно отфильтровать)
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END as PersonType, circt_cstdn_nm FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d INNER JOIN dbo.circt_cstdn on circt_cstdn_user_id = CASE WHEN d.i = 1 THEN circt.circt_cstdn_user_id WHEN d.i = 2 THEN dvc.circt_cstdn_user_id END GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END, circt_cstdn_nm
Создайте представление, используя это и создайте индекс
create VIEW vw_lookup_test_imed WITH SCHEMABINDING AS <<query above>> GO spell to create INDEX
Теперь вы поворачиваете, чтобы преобразовать столбец Persontype на владельца и технологии
SELECT count_all, awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, [Owner], [Tech] FROM ( SELECT count_all, awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, PersonType, circt_cstdn_nm FROM dbo.vw_lookup_test_imed WITH (NOEXPAND) ) src PIVOT ( MAX(circt_cstdn_nm) FOR PersonType IN ([Owner], [Tech]) ) pvt
Если есть синтаксические ошибки (есть большие возможности, потому что у меня нет доступа к базе данных прямо сейчас) Дайте мне знать.
Другие советы
Я думаю, что этот синтаксис присоединения ужасен и возник из MS Access. фу. Я рекомендую вам использовать:
select
count_big(*) as [count_all],
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm [owner],
t.circt_cstdn_nm [tech],
dvc.circt_nm,
data_orgtn_yr
-- HERE
from dbo.dvc
join dbo.circt on (dvc.circt_nm = circt.circt_nm)
join dbo.circt_cstdn o on (circt.circt_cstdn_user_id = o.circt_cstdn_user_id)
join dbo.circt_cstdn t on (dvc.circt_cstdn_user_id = t.circt_cstdn_user_id)
group by
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm,
t.circt_cstdn_nm,
dvc.circt_nm,
data_orgtn_yr
Этот синтаксис является очистителем, более приемлемым и распознается в SQL Server, Firebird, Oracle, MySQL и многих других. Теперь вы можете увидеть лучшие отношения между «столами». Когда вы присоединяетесь к тому же «таблицу« два или более раз, вам нужно псевдоним каждый. На одной строке «CIRCT_CSTDN» псевдонится как «O». На другой строке «CIRCT_CSTDN» псевдонится как «T».
Я рекомендую использовать левое соединение или внутреннее соединение вместо присоединения.