postgresql 将 UNNEST 与 JOIN 一起使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16054925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using UNNEST with a JOIN
提问by ?lker ?nan?
I want to be able to use unnest()
function in PostgreSQL in a complicated SQL query that has many JOIN
s. Here's the example query:
我希望能够unnest()
在具有许多JOIN
s的复杂 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
I want to eliminate the taggings
table here, because my mentions
table has an integer arrayfield named taglistthat consists of all linked tag ids of mentions
.
我想消除taggings
这里的表,因为我的mentions
表有一个名为taglist的整数数组字段,它由.mentions
I tried following:
我尝试了以下操作:
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
This works but brings different results than the first query.
这有效,但带来了与第一个查询不同的结果。
So what I want to do is to use the result of the SELECT unnest(taglist)
in a JOIN
query to compensate for the taggings
table.
因此,我想要做的是使用的结果SELECT unnest(taglist)
的JOIN
查询,以补偿taggings
表。
How can I do that?
我怎样才能做到这一点?
UPDATE:taglist
is the same set as the respective list of tag ids of mention.
更新:taglist
与提及的标签 ID 的相应列表相同。
采纳答案by Erwin Brandstetter
Technically, your query might work like this (not entirely sure about the objective of this query):
从技术上讲,您的查询可能像这样工作(不完全确定此查询的目标):
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;
However, it seems to me you are going in the wrong direction here. Normally one would remove the redundant array taglist
and keep the normalized database schema. Then your original query should serve well, only shortened the syntax with aliases:
但是,在我看来,您在这里走错了方向。通常,人们会删除冗余数组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;
Unravel the mystery
揭开谜底
<rant>
The root cause for your "different results" is the unfortunate naming convention that some intellectually challenged ORMsimpose on people.
I am speaking of
as column name. Never use this anti-pattern in a database with more than one table. Right, that means basically anydatabase. As soon as you join a bunch of tables (that's what you doin a database) you end up with a bunch of columns named idid
. Utterly pointless.
The ID column of a table named tag
should be tag_id
(unless there is another descriptive name). Never id
.
</rant>
<rant>
您的“不同结果”的根本原因是一些在智力上受到挑战的 ORM强加给人们的不幸的命名约定。
我说的
是列名。切勿在具有多个表的数据库中使用此反模式。是的,这意味着基本上任何数据库。一旦你加入了一堆表(这就是你在数据库中所做的),你最终会得到一堆名为idid
. 完全没有意义。
命名的表的 ID 列tag
应该是tag_id
(除非有另一个描述性名称)。从来没有id
。
</rant>
Your query inadvertently counts tags
instead of mentions
:
您的查询无意中计数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;
It should work this way:
它应该这样工作:
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;
I also added back the DISTINCT
to your count()
that got lost along the way in your query.
我还添加回DISTINCT
您count()
在查询过程中丢失的 。
回答by Wojtas
Something like this should work:
这样的事情应该工作:
...
tags t INNER JOIN
(SELECT UNNEST(taglist) as idd) a ON t.id = a.idd
...