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の関係があります。

特定の統計を確認したいと思います。1つの統計は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(コーム)が2回あるため、CROSSJOINが2回実行されることに注意してください。

2つ目は、それが明らかになったら、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で完全にカバーされているため、CLASSESをミックスに追加する価値は実際にはありません。最初の部分も書くことができます

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

次に注意すべきことは、CROSS JOINは、定義上、GROUPBYを役に立たなくすることです。これらは常に一意です。

2番目の部分は次のように簡略化されます

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

以来

  • CROSSは、(ドキュメントを持つ)すべてのクラスをトークンに結合します。と
  • B CROSSは、(ドキュメントを持つ)すべてのトークンをクラスに結合します

交差点は明らかに、同じドキュメントID上のドキュメントに存在するドキュメントINNERJOINクラスに存在するトークンです。

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 に答える