我希望能够在一个复杂的SQL查询中使用PostgreSQL中的unnest()
函数,该查询有很多JOIN
个。这是示例查询:
SELECT 9 as keyword_id, COUNT(DISTINCT mentions.id) as total, tags.parent_id as tag_id
FROM mentions
INNER JOIN taggings ON taggings.mention_id = mentions.id
INNER JOIN tags ON tags.id = taggings.tag_id
WHERE mentions.taglist && ARRAY[9] AND mentions.search_id = 3
GROUP BY tags.parent_id
我想在此删除taggings
表,因为我的mentions
表有一个名为 taglist 的整数数组字段,其中包含所有链接标记ID mentions
。
我试过以下:
SELECT 9 as keyword_id, COUNT(DISTINCT mentions.id) as total, tags.parent_id as tag_id
FROM mentions
INNER JOIN tags ON tags.id IN (SELECT unnest(taglist))
WHERE mentions.taglist && ARRAY[9] AND mentions.search_id = 3
GROUP BY tags.parent_id
这可行,但会带来与第一个查询不同的结果。
所以我想要做的是在SELECT unnest(taglist)
查询中使用JOIN
的结果来补偿taggings
表。
我该怎么做?
更新: taglist
与相应的标记ID列表相同。
答案 0 :(得分:5)
从技术上讲,您的查询可能会像这样工作(不完全确定此查询的目标):
SELECT 9 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id AS tag_id
FROM (
SELECT unnest(m.taglist) AS tag_id
FROM mentions m
WHERE m.search_id = 3
AND 9 = ANY (m.taglist)
) m
JOIN tags t USING (tag_id) -- assumes tag.tag_id!
GROUP BY t.parent_id;
然而,在我看来,你在这里走错了方向。通常会删除冗余数组taglist
并保留规范化的数据库模式。然后你的原始查询应该很好用,只用别名缩短语法:
SELECT 9 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id AS tag_id
FROM mentions m
JOIN taggings mt ON mt.mention_id = m.id
JOIN tags t ON t.id = mt.tag_id
WHERE 9 = ANY (m.taglist)
AND m.search_id = 3
GROUP BY t.parent_id;
<rant>
“不同结果”的根本原因是一些智力挑战ORM 强加给人们的不幸命名惯例。
我说的是
作为列名。切勿在具有多个表的数据库中使用此反模式。对,这基本上意味着任何数据库。一旦你加入一堆表(这就是你在数据库中做的),你就会得到一堆名为idid
的列。毫无意义
名为tag
的表的ID列应为 tag_id
(除非有另一个描述性名称)。永远不会id
。
</rant>
您的查询无意中计入tags
而不是mentions
:
SELECT 25 AS keyword_id, count(m.id) AS total, t.parent_id AS tag_id
FROM (
SELECT unnest(m.taglist) AS id
FROM mentions m
WHERE m.search_id = 4
AND 25 = ANY (m.taglist)
) m
JOIN tags t USING (id)
GROUP BY t.parent_id;
它应该以这种方式工作:
SELECT 25 AS keyword_id, count(DISTINCT m.id) AS total, t.parent_id
FROM (
SELECT m.id, unnest(m.taglist) AS tag_id
FROM mentions m
WHERE m.search_id = 4
AND 25 = ANY (m.taglist)
) m
JOIN tags t ON t.id = m.tag_id
GROUP BY t.parent_id;
我还将DISTINCT
添加回您count()
的{{1}},这些{{1}}在查询过程中丢失了。
答案 1 :(得分:1)
这样的事情应该有效:
...
tags t INNER JOIN
(SELECT UNNEST(taglist) as idd) a ON t.id = a.idd
...