1

我有一个定义如下的数据库:

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

文档与类、文档与令牌之间存在 am: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 的最有效方法吗?如果没有,有更好的方法吗?我还可以更改底层数据库结构以潜在地加快速度......

任何反馈将不胜感激。

4

2 回答 2

3

首先,即使您已将其设为 CTE,请记住,因为您在查询中有两次 CTE(梳子),所以 CROSS JOIN 执行了两次

第二个是一旦清楚了,您应该只继承 ID 并在最后加入以获取文本。

第一部分真的

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

这意味着,将 CLASSES 添加到组合中确实没有任何价值,因为它已由 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 将所有类(具有文档)连接到令牌;和
  • B 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
于 2011-02-01T09:25:06.980 回答
-1

将其重写为单个内部连接,以使优化器的工作更轻松

于 2011-02-01T09:21:14.540 回答