2010-06-15 49 views
3

就像你可能知道的那樣,你不能通過自聯接爲一個視圖建立索引。實際上,甚至連同一張表的兩個連接,即使它不是技術上的自連接。微軟的幾個人提出了一個解決方案。但它太複雜了,我不明白!需要一些自我加入問題的認真幫助

的問題的解決方案是在這裏: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 

任何幫助將大大apreciated!

非常感謝!

編輯:所以我發現這也將工作。請注意,我在第一個索引視圖中加入表格一次,第二次在第二個非索引視圖中加入表格。

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指標如我所願。我不確定此解決方案(或解決方案)是否會提高性能,但我會通知您。

回答

1

這就是我從博客帖子有

  • 比方說,你想加入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 
    ... 
    
  • 然後你轉動的名稱列的最大業主和技術。注意 - 最大值函數只是欺騙PIVOT(需要一些聚合函數),如果只有一條記錄,則可以使用任何聚合函數返回相同的值 owner tech row1 nm nm ...

現在,如果我們這樣做,爲您的查詢

  1. 創建一個表d,像這樣的

    i 
    1 
    2 
    
  2. CROSS JOIN查詢與此

    第一部分
    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. 否W¯¯讓我們使用該行的老闆,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. 現在添加納米柱。要獲取名稱,如果它是所有者行(d.i = 1),則使用circt加入circt_cstdn,如果是tech行(d.i = 2),則使用dvc加入circt_cstdn。注意 - 我通過將這個放在連接條件中來嘗試一個快捷方式。如果它不工作,嘗試博客文章的方式(做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列轉換爲業主和技術列

    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

是您最後一次查詢您發佈了另一個視圖嗎?因爲我的理解是我不能索引引用另一個視圖的視圖......或者我要索引第一個視圖?並使用第二個...? – kralco626 2010-06-16 12:03:22

+0

O.K.我重讀了你的帖子,我很確定我會索引第一個視圖。但是,我如何索引第一個視圖? – kralco626 2010-06-16 12:06:51

+0

好吧!我創建了第一個視圖。創建了一個超過8列的獨特聚集索引,然後我從第二個視圖運行select語句,並獲得了300486行而不是299925,這是我運行原始語句時得到的數量。大聲笑你preformed魔術:)你創造了561行...任何想法? – kralco626 2010-06-16 13:52:07

0

我認爲這個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,火鳥,甲骨文,MySQL和其他多是公認的。 現在你可以更好地看到「表格」之間的關係。 當您連接兩次或更多次相同的「表」時,您需要爲每個表添加別名。在一行中,「circt_cstdn」被別名爲「o」。在其他行上,「circt_cstdn」的別名爲「t」。

我建議使用LEFT JOIN或INNER JOIN來代替JOIN。

+0

兩件事。首先,我完全同意你的看法:我總是使用左連接。但是,您無法使用左連接爲視圖建立索引,並且我對其進行了測試,並且以任何方式獲得了相同的結果。 其次,我認爲你剛剛發佈的內容與我在原始文章中發佈的內容幾乎完全相同......我確實使用了別名O和T ...... – kralco626 2010-06-16 12:00:36

+0

而且我認爲你可能意味着我通過數據庫知識來自MSAccess!我討厭MsAccess。 (使用的SQL語言具有愚蠢的限制和糟糕)。 「INNER JOIN」與「JOIN」完全相同...... – kralco626 2010-06-17 12:21:35