我已经构建了一个程序来索引文本文件中的关键字并将它们放到数据库中。
我的表很简单:
FILE_ID|Name
------------
1 | a.txt
2 | b.txt
3 | c.txt
KEYWORD_ID|FILE_ID|Hits
-----------------------
1 | 1 | 55
2 | 1 | 10
3 | 1 | 88
1 | 2 | 44
2 | 2 | 15
1 | 3 | 199
2 | 3 | 1
3 | 3 | 4
此表中没有主键。我没有发现它是必要的。
现在,我想搜索哪个文件对某些关键字的匹配率最高。
如果我只有一个关键字,那么很容易:
select top 10 *
from words
where keyword_id=1
order by hits desc
假设我想搜索带有关键字1和3的文件(两者都必须存在且第一个关键字具有最高重要性)。几个小时后,我来到这里:
select top 10 k.*
from
(
select file_id,
max(hits) as maxhits
from words
where keyword_id=3
group by file_id
) as x
inner join keyword as k
on (k.file_id = x.file_id
and k.keyword=1)
order by k.hits desc
如何做到这一点?特别是如果我想用N个关键字搜索。使用临时表并使用它会更好吗?
如果使用关键字1和3进行搜索,我希望按此顺序返回FILE_ID 3和1(因为file_id 3对关键字1的命中次数较高)
答案 0 :(得分:1)
不确定,但(根据您的评论)可能是您需要的吗?
(我使用@scsimon回答的表声明)
declare @words table (KEYWORD_ID int, [FILE_ID] int, HITS int)
insert into @words
values
(1,1,55),
(2,1,10),
(3,1,88),
(1,2,44),
(2,2,15),
(1,3,199),
(2,3,1),
(3,3,4)
select [FILE_ID] from (
select *, row_number() over(partition by KEYWORD_ID order by HITS desc) rn from @words
where KEYWORD_ID in(1,3)
)t
where rn = 1
order by hits desc
答案 1 :(得分:1)
假设要找到的所有相关关键字都存储在表KTable
中,该表有两列ID
和KEYWORD_ID
然后查询应该是
SELECT
FileID,
SUM(Hits) NetHits,
SUM(Hits/K.ID) WeightedHits
FROM
Words w JOIN Ktable K
on w.KEYWORD_ID= K.KEYWORD_ID
GROUP BY FileID
HAVING count(1) = (SELECT COUNT(1) FROM Ktable )
ORDER BY 2 DESC,3 DESC
使用Windowing函数的相同查询将是
SELECT
DISTINCT
FileID,
NetHitsPerFile
FROM
(
SELECT
FileID,
SUM(Hits) OVER (PARTITION BY FileID ORDER BY K.ID ASC) NetHitsPerFile,
SUM(FileID) OVER(PARTITION BY K.ID) Files,
SUM(Hits/K.ID) OVER (PARTITION BY FileID ORDER BY K.ID ASC) weightedHits
FROM
Words w JOIN Ktable K
on w.KEYWORD_ID= K.KEYWORD_ID
)T
WHERE Files= (SELECT COUNT(1) FROM Ktable)
ORDER BY NetHitsPerFile, weightedHits
答案 2 :(得分:0)
以下单行方式...如果您只想查看指定KEYWORD_ID
的行,只需在底部添加WHERE CLAUSE
即可。 INNER JOIN
将FILE_ID
限制为包含您指定的 KEYWORD_ID
的{{1}},方法是检查非重复计数是否=关键字数量。因此,在下面的示例中,我们将结果集限制为2 KEYWORD_ID
并检查以确保每个FILE_ID
有2个不同的KEYWORD_ID
关联,HAVING
子句
declare @words table (KEYWORD_ID int, [FILE_ID] int, HITS int)
insert into @words
values
(1,1,55),
(2,1,10),
(3,1,88),
(1,2,44),
(2,2,15),
(1,3,199),
(2,3,1),
(3,3,4)
select top 10 w.*
from @words w
inner join
(select [FILE_ID]
from @words
where KEYWORD_ID in (1,3)
group by [FILE_ID]
having count(distinct KEYWORD_ID) = 2
) x on x.[FILE_ID] = w.[FILE_ID]
order by HITS desc
答案 3 :(得分:0)
您可以将top(n)与tie结合使用,如下所示:
declare @n int = 10 --10 in your scenario
select top (@n) with ties *
from (
select w.*, f.name from #words w inner join #files f
on w.[FILE_ID] = f.[file_id]
) a
order by (row_number() over (partition by a.[file_id] order by hits desc)-1)/@n +1