寻求返回与媒体文件匹配的所有标签的方法

问题描述 投票:0回答:1

我之前问了一个问题,但有点搞砸了,所以我在这里再次重新表述。

我有3个相关的表:

  • media
  • media_tags
    (桥台)
  • tags

这是我到目前为止的代码:

SELECT m.media_id, m.name, array_agg(distinct t.tag) filter (WHERE t.date_deleted IS NULL) AS tags 
FROM media m 
LEFT JOIN media_tags mt USING (media_id) 
LEFT JOIN tags t USING (tag_id)
WHERE m.date_deleted IS NULL AND t.tag = ANY(array['dog','cat'])
GROUP BY m.media_id, m.name

这非常接近我想要的,但并不完全正确。 想象一下有这些媒体记录:

  • 媒体 1 带有这些标签:狗、鸟、羊、马
  • 媒体 2 带有这些标签:狗、猫、牛
  • 媒体 3 带有这些标签:猫、马、兔子
  • 媒体 4 带有这些标签:牛、马、羊

我上面的查询确实返回媒体 1、2 和 3,但显示的标签仅包含

dog
cat
。 我想要的是
tags
始终包含其所有标签(如果与数组中的任何值有任何匹配)。 因此,如果 ['dog','cat'] 在查询中,则媒体 1、2 和 3 应返回其各自的所有标签,但媒体 4 不应返回,因为没有匹配项。

我感觉我已经非常接近解决方案,但就是无法弄清楚。

postgresql join
1个回答
0
投票

执行此操作的 ANSI 标准方法(不使用 Postgres 数组)是首先查找所有匹配的标签,然后使用该结果来限制当前查询。

WITH cte AS (
    SELECT m.media_id
    FROM media m
    INNER JOIN media_tags mt ON mt.media_id = m.media_id
    INNER JOIN tags t ON t.tag_id = mt.tag_id
    WHERE t.tag IN ('dog', 'cat')
    GROUP BY m.media_id
    HAVING COUNT(DISTINCT t.tag) = 2
)

SELECT m.media_id, m.name, ARRAY_AGG(DISTINCT t.tag) FILTER (WHERE t.date_deleted IS NULL) AS tags
FROM media m
INNER JOIN media_tags mt ON mt.media_id = m.media_id
INNER JOIN tags t ON t.tag_id = mt.tag_id
WHERE m.media IN (SELECT media_id FROM cte)
GROUP BY m.media_id, m.name;
© www.soinside.com 2019 - 2024. All rights reserved.