我有三个主要项目:文章,实体和关键字。这使得5个表:
article { id }
entity {id, name}
article_entity {id, article_id, entity_id}
keyword {id, name}
article_keyword {id, article_id, keyword_id}
我想获得包含TOP X关键字+实体的所有文章。我可以使用entity_id/keyword_id
上的简单组获得前X个关键字或实体。
SELECT [entity|keyword]_id, count(*) as num FROM article_entity
GROUP BY entity_id ORDER BY num DESC LIMIT 10
我如何获得与顶级实体和关键字有关系的所有文章?
这是我想象的,但我知道它不起作用,因为逐个实体限制了返回的article_id。
SELECT * FROM article
WHERE EXISTS (
[... where article is mentioned in top X entities.. ]
) AND EXISTS (
[... where article is mentioned in top X keywords.. ]
);
答案 0 :(得分:2)
如果我理解你正确的话,查询的目的是找到与前10个实体之一以及前10个关键字之一有关系的文章。如果是这种情况,则以下查询应该这样做,方法是要求返回的文章在前10个实体集和前10个关键字集中都匹配。
请试一试。
SELECT a.id
FROM article a
INNER JOIN article_entity ae ON a.id = ae.article_id
INNER JOIN article_keyword ak ON a.id = ak.article_id
INNER JOIN (
SELECT entity_id, COUNT(article_id) AS article_entity_count
FROM article_entity
GROUP BY entity_id
ORDER BY article_entity_count DESC LIMIT 10
) top_ae ON ae.entity_id = top_ae.entity_id
INNER JOIN (
SELECT keyword_id, COUNT(article_id) AS article_keyword_count
FROM article_keyword
GROUP BY keyword_id
ORDER BY article_keyword_count DESC LIMIT 10
) top_ak ON ak.keyword_id = top_ak.keyword_id
GROUP BY a.id;
在顶级实体/关键字的两个子查询中使用简单limit 10
的缺点是它不会处理关系,因此如果第11个关键字与第10个关键字一样受欢迎,它仍然无法获得选择。这可以通过使用排名函数来修复,但是没有内置任何东西(如Oracle或MSSQL中的RANK()窗口函数)。
我设置了一个示例SQL Fiddle(但是我使用的数据点更少,limit 2
因为我很懒。)
答案 1 :(得分:2)
不知道您使用的数据量,我建议您在文章表中分别有两个存储列,分别用于实体和关键字的数量。然后通过添加/删除每个触发器的触发器,更新相应的计数器列。这样,您就不必在每次需要时进行刻录查询,尤其是在基于Web的界面中。然后,您可以从E + K计数降序排序的文章表中选择并完成它,而不是不断查询基础表。
现在,这就是说,其他建议有点类似于我发布的内容,但它们似乎都在为每个集合限制10条记录。让我们把这个场景投入到图片中。假设您有文章1-20所有10,9和8个实体以及1-2个关键字。然后文章21-50具有相反的... 10,9,8个关键字和1-2个实体。现在,您有51-58条文章,其中包含7个实体和7个关键字,共有14个组合点。由于实体只会返回符合条件的1-20记录和关键字记录21-50,因此没有任何查询会捕获此信息。到目前为止,第51-58条将列在名单上,即使总数为14,也不会被考虑。
要处理此问题,每个子查询都是一个完整的查询,特别是关于文章ID及其计数。 article_ID的简单顺序,因为它是连接到主文章表的基础。
现在,coalesce()将获得计数(如果可用),否则为0并将两个值相加。从那时起,结果按照最高计数排序(因此在应用限制时获得情景样本文章51-58加上其他一些)。
SELECT
a.id,
coalesce( JustE.ECount, 0 ) ECount,
coalesce( JustK.KCount, 0 ) KCount,
coalesce( JustE.ECount, 0 ) + coalesce( JustK.KCount, 0 ) TotalCnt
from
article a
LEFT JOIN ( select article_id, COUNT(*) as ECount
from article_entity
group by article_id
order by article_id ) JustE
on a.id = JustE.article_id
LEFT JOIN ( select article_id, COUNT(*) as KCount
from article_keyword
group by article_id
order by article_id ) JustK
on a.id = JustK.article_id
order by
coalesce( JustE.ECount, 0 ) + coalesce( JustK.KCount, 0 ) DESC
limit 10
答案 2 :(得分:1)
我分几步采取了这个步骤
tl; dr 这会显示top(4)关键字和实体中的所有文章:
这是fiddle
select
distinct article_id
from
(
select
article_id
from
article_entity ae
inner join
(select
entity_id, count(*)
from
article_entity
group by
entity_id
order by
count(*) desc
limit 4) top_entities on ae.entity_id = top_entities.entity_id
union all
select
article_id
from
article_keyword ak
inner join
(select
keyword_id, count(*)
from
article_keyword
group by
keyword_id
order by
count(*) desc
limit 4) top_keywords on ak.keyword_id = top_keywords.keyword_id) as articles
说明:
首先是努力寻找前X个实体。 (4似乎适用于我想在小提琴中制作的协会数量)
我不想在这里选择文章,因为它会使群体产生偏差,你只想专注于顶级实体。 Fiddle
select
entity_id, count(*)
from
article_entity
group by
entity_id
order by
count(*) desc
limit 4
然后我选择了这些顶级实体的所有文章。 Fiddle
select
*
from
article_entity ae
inner join
(select
entity_id, count(*)
from
article_entity
group by
entity_id
order by
count(*) desc
limit 4) top_entities on ae.entity_id = top_entities.entity_id
显然,关键字需要采用相同的逻辑。然后将查询union
放在一起(fiddle),并从联合中提取不同的文章ID。
这将为您提供与top(x)实体和关键字有关的所有文章。
答案 3 :(得分:0)
这将获得前十大关键字文章,这些文章也是十大实体。您可能无法获得10条记录,因为文章可能只符合其中一个条件(顶级实体但不是顶级关键字或顶级关键字,但不符合顶级实体)
select *
from article a
inner join
(select count(*),ae.article_id
from article_entity ae
group by ae.article_id
order by count(*) Desc limit 10) e
on a.id = e.article_id
inner join
(select count(*),ak.article_id
from article_keyword ak
group by ak.article_id
order by count(*) Desc limit 10) k
on a.id = k.article_id