我的数据库定义如下:
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)
)
文档与类,文档和标记之间存在m: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 :(得分: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
这意味着,实际上没有任何值将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
由于
交集显然只是存在于同一文档文档中的文档INNER JOIN类中的标记,例如。
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 :(得分:-1)
将其重写为单个内部联接,以使优化程序更轻松