9

我希望能够unnest()在具有许多JOINs 的复杂 SQL 查询中使用 PostgreSQL 中的函数。这是示例查询:

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的整数数组字段,其中包含.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 列表相同。

4

2 回答 2

8

从技术上讲,您的查询可能会像这样工作(不完全确定此查询的目标):

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强加给人们的不幸的命名约定。
我说的id是列名。切勿在具有多个表的数据库中使用此反模式。对,这基本上意味着任何数据库。一旦你加入一堆表(这就是你在数据库中所做的),你最终会得到一堆名为id. 完全没有意义。
命名表的 ID 列tag应该是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()

于 2013-04-17T21:40:05.800 回答
2

像这样的东西应该工作:

...
tags t INNER JOIN
(SELECT UNNEST(taglist) as idd) a ON t.id = a.idd
...
于 2013-04-17T09:41:10.590 回答