如何获取缺少posgtres中某个标记的文章?

huwehgph  于 2021-07-24  发布在  Java
关注(0)|答案(4)|浏览(348)

我有一个要求,允许过滤没有标签的文章。
e、 g.我有:

articles.id
A
B
tags.id
1
2
3
4
articles_tags.article_id articles_tags.tag_id
A 1
A 2
B 2
B 4

现在,我有一个标签ID列表,例如。 (3, 4) . 我想一个查询,返回的文章是缺少任何标签的列表。在本例中,它将同时返回a和b,因为它们都没有标记3。如果我送 (1) 它应该只返回 B 因为a有标签1。

3vpjnl9f

3vpjnl9f1#

你可以用 not exists 和聚合查询:

select a.*
from articles a
where (
    select count(*) 
    from article_tags at 
    where at.article_id = a.id and at.tag_id in (3, 4)
) < 2

这是假定在上没有重复项 article_tags(article_id, tag_id) (如示例数据所示)。
您还可以在一个 having 条款:

select a.*
from articles a
inner join article_tags at on at.article_id = a.id
group by a.id
having count(*) filter(where at.tag_id in (3, 4)) < 2
wvmv3b1j

wvmv3b1j2#

我将使用postgresql数组类型来处理这个问题。
忽略 articles 以及 tags 要简化的表:

with arraystyle as (
  select article_id, array_agg(tag_id) as tagarray
    from articles_tags
   group by article_id
)
select * from arraystyle;

 article_id | tagarray
------------+-----------
 B          | {2,4}
 A          | {1,2}
(2 rows)

使用此格式的tagarray可以使用数组函数和运算符。安全壳操作员之一, @> 以及 <@ ,是你所需要的否定形式。

with arraystyle as (
  select article_id, array_agg(tag_id) as tagarray
    from articles_tags 
   group by article_id
)
select * from arraystyle
 where not tagarray @> '{1,3}';

 article_id | tagarray 
------------+----------
 B          | {2,4}
 A          | {1,2}
(2 rows)

with arraystyle as (
  select article_id, array_agg(tag_id) as tagarray
    from articles_tags 
   group by article_id
)
select * from arraystyle
 where not tagarray @> '{1}';

 article_id | tagarray 
------------+----------
 B          | {2,4}
(1 row)
ybzsozfc

ybzsozfc3#

试试这个:

select 
distinct article_id 
from (   
 select 
 t1.id as "article_id",
 t2.id as "articles_tags"
 from articles t1 cross join tags t2 where t2.id in (3,4)
 except
 ( select 
article_id,
tag_id from articles_tags where tag_id in (3,4) ) ) tab

演示
这将在组合的重复条目的情况下处理

zte4gxcn

zte4gxcn4#

一种方法是 not exists :

select a.*
from articles a
where not exists (select 1 from article_tags art where art.article_id = a.id and art.tag = 3) or
      not exists (select 1 from article_tags art where art.article_id = a.id and art.tag = 4) ;

也可以使用集合操作:

select a.id
from articles a
except
(select art.article_id
 from article_tags art
 where art.tag = 3
 intersect
 select art.article_id
 from article_tags art
 where art.tag = 4
);

相关问题