2011-02-01 53 views
1

我有一個數據庫定義如下:SQL Server的查詢相交

create table Classes (
    Id INT not null, 
    Text NVARCHAR(255) null, 
    primary key (Id) 
) 

create table Documents (
    Id INT not null, 
    Title NVARCHAR(MAX) null, 
    Abstract NVARCHAR(MAX) null, 
    Year INT null, 
    primary key (Id) 
) 

create table Documents_Tokens (
    DocumentFk INT not null, 
    TokenFk INT not null 
) 

create table Documents_Classes (
    DocumentFk INT not null, 
    ClassFk INT not null 
) 

create table Tokens (
    Id INT not null, 
    Text NVARCHAR(255) null, 
    primary key (Id) 
) 

有A M:文件和類文件和令牌米之間的關係。

我想確定某些統計數據。一個屬性是A,它衡量類和代幣的共同出現。我目前確定這個統計是這樣的:

with combs as 
(
    select 
     a.Id as classid, 
     a.text as class, 
     b.Id as tokenid, 
     b.text as token 
     from dbo.Classes as a 
     cross join dbo.Tokens as b 
) 
,A as 
(
    select token, class, count(distinct DocumentFk) as A from 
    (
     select 
      token, 
      class, 
      DocumentFk 
     from combs 
     inner join dbo.Documents_Classes on classid = ClassFk 
     group by token, DocumentFk, class 
      intersect 
     select 
      token, 
      class, 
      DocumentFk 
     from combs 
     inner join dbo.Documents_Tokens on tokenid = tokenFk 
     group by token, DocumentFk, class 
    ) T group by token, class 
) 
... 

不幸的是,這個查詢需要年齡(我已經運行查詢分析器後添加索引)。這是確定A的最有效方法嗎?如果沒有更好的方法?我也可以改變潛在的數據庫結構,以加快速度...

任何反饋將非常感激。

+0

梳子從哪裏來? – RichardTheKiwi 2011-02-01 09:13:34

回答

3

首先,是因爲你有CTE(梳),即使你做了它的CTE,牢記更容易兩次查詢,CROSS JOIN執行TWICE

第二個是,一旦變得清晰,你應該只發揚ID,並在最後加入獲取文本。

第一部分是真的

select 
     token, 
     class, 
     DocumentFk 
    from (--> expanded = tokens cross join classes <--) 
    inner join dbo.Documents_Classes on classid = ClassFk 
    group by token, DocumentFk, class 

這意味着,實在是沒有增值類的搭配,因爲它完成覆蓋Documents_Classes。第一部分也可以被寫入

select 
     token_id, 
     class_id, 
     DocumentFk 
    from TOKENS 
    CROSS join dbo.Documents_Classes 
    --group by token_id, DocumentFk, class_id 

下一個要注意的是,通過CROSS JOIN定義呈現GROUP BY無用的 - 他們總是獨一無二的。

第二部分簡化爲

select 
     token_id, 
     class_id, 
     DocumentFk 
    from CLASSES 
    CROSS join dbo.Documents_Tokens 

由於

  • 交叉連接所有類(有證件)到令牌;和
  • 乙CROSS聯接所有令牌(具有文件)到類

交點顯然簡單地存在於文檔INNER JOIN,在文件存在於同一documentid類,例如令牌

select C.text class, T.text token, count(DC.DocumentFk) as CountDocument 
from Documents_Classes DC 
inner join Documents_Tokens DT on DC.DocumentFk = DT.DocumentFk 
inner join Classes C on DC.classFk = c.id 
inner join Tokens T on DT.tokenFk = t.id 
group by C.text, T.text, C.id, T.id 
-1

重寫它作爲一個單一的內部連接,使生活,爲優化