У меня есть документы, которые могут принадлежать нескольким классам и содержать несколько токенов (слов):
create table Tokens (
Id INT not null,
Text NVARCHAR(255) null,
primary key (Id)
)
create table DocumentClassTokens (
Id INT not null,
DocumentFk INT null,
ClassFk INT null,
TokenFk INT null,
primary key (Id)
)
Я бы хотел определить эти характеристики (для всех жетонов данного класса):
- A = количество отдельных документов, которые содержат токен и относятся к классу
- B = количество отдельных документов, которые содержат токен и не относятся к классу
- C = количество отдельных документов, которые не содержат токена и относятся к классу
- D = количество отдельных документов, которые не содержат токена и не относятся к классу
Я использую это в данный момент, но это выглядит неправильно (я почти уверен, что вычисления A и B правильные):
declare @class int;
select @class = id from dbo.Classes where text = 'bla'
;with A as
(
select
a.text as token,
count(distinct DocumentFk) as A
from dbo.Tokens as a
inner join dbo.DocumentClassTokens as b on a.id = b.TokenFk and b.ClassFk = @class
group by a.text
)
,B as
(
select
a.text as token,
count(distinct DocumentFk) as B
from dbo.Tokens as a
inner join dbo.DocumentClassTokens as b on a.id = b.TokenFk and b.ClassFk != @class
group by a.text
)
,C as
(
select
a.text as token,
count(distinct DocumentFk) as C
from dbo.Tokens as a
inner join dbo.DocumentClassTokens as b on a.id != b.TokenFk and b.ClassFk = @class
group by a.text
)
,D as
(
select
a.text as token,
count(distinct DocumentFk) as D
from dbo.Tokens as a
inner join dbo.DocumentClassTokens as b on a.id != b.TokenFk and b.ClassFk != @class
group by a.text
)
select
case when A is null then 0 else A end as A,
case when B is null then 0 else B end as B,
case when C is null then 0 else C end as C,
case when D is null then 0 else D end as D,
t.Text,
t.id
from dbo.Tokens as t
left outer join A as a on t.text = a.token
left outer join B as b on t.text = b.token
left outer join C as c on t.text = c.token
left outer join D as d on t.text = d.token
order by t.text
Любая обратная связь будет принята с благодарностью. Большое спасибо!
С наилучшими пожеланиями,
Christian
PS:
Некоторые данные испытаний:
use play;
drop table tokens
create table Tokens
(
Id INT not null,
Text NVARCHAR(255) null,
primary key (Id)
)
insert into Tokens (id, text) values (1,'1')
insert into Tokens (id, text) values (2,'2')
drop table DocumentClassTokens
create table DocumentClassTokens (
Id INT not null,
DocumentFk INT null,
ClassFk INT null,
TokenFk INT null,
primary key (Id)
)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (1,1,1,1)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (2,1,1,2)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (3,2,1,1)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (4,2,2,1)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (5,3,2,1)
insert into DocumentClassTokens (Id,documentfk,ClassFk,TokenFk) values (6,3,2,3)