Нужна серьезная помощь с самостоятельной проблемой присоединения - PullRequest
3 голосов
/ 15 июня 2010

Как вы, наверное, знаете, вы не можете индексировать представление с помощью самостоятельного объединения. Ну, на самом деле даже два соединения одной и той же таблицы, даже если это технически не самостоятельное соединение. Пара ребят из Microsoft придумали обходной путь. Но это так сложно, я этого не понимаю !!!

Решение проблемы здесь: http://jmkehayias.blogspot.com/2008/12/creating-indexed-view-with-self-join.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

Затем я могу создавать индексы дополнений в первом представлении по своему желанию. Я не уверен, что это решение (или обходной путь в этом отношении) действительно ускорит выполнение, но я дам вам знать.

Ответы [ 2 ]

1 голос
/ 16 июня 2010

Вот что я получил из поста в блоге

  • Допустим, вы хотите присоединиться 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
    ...
    
  • Затем вы поворачиваетесь на столбце max of name для владельца и технологии. Примечание: функция max предназначена только для обмана PIVOT (для этого требуется некоторая агрегатная функция), вы можете использовать любую агрегатную функцию, которая возвращает то же значение, если есть только одна запись владелец технологии ряд1 нм нм ...

Теперь, если мы сделаем это для вашего запроса

  1. Создать таблицу d, как эта

     i
     1
     2
    
  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
    
  3. Теперь давайте используем строку для владельца, если D.i равен 1, и технологию, если D.i равен 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  
    
  4. Теперь добавьте столбец nm. Чтобы получить имя, вы присоединяетесь к circt_cstdn с circt, если это строка владельца (d.i = 1), и с dvc, если это техническая строка (d.i = 2). Примечание. Я попытался использовать ярлык, поместив его в состояние соединения. Если это не сработает, попробуйте написать в блоге (присоединитесь к circt.circt_cstdn_user_id ИЛИ dvc.circt_cstdn_user_id, а затем используйте предложение WHERE для фильтрации)

    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
    
  5. Создайте представление, используя это и создайте индекс

    create VIEW vw_lookup_test_imed
    WITH SCHEMABINDING 
    AS
        <<query above>>  
    GO
    
    spell to create INDEX
    
  6. Теперь вы PIVOT для преобразования столбца PersonType в столбцы Owner и Tech

    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 
    

Если есть синтаксические ошибки (их должно быть много, потому что у меня сейчас нет доступа к базе данных), сообщите мне.

0 голосов
/ 16 июня 2010

Я думаю, что этот синтаксис JOIN ужасен и возник из 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".

Я рекомендую использовать LEFT JOIN или INNER JOIN вместо JOIN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...