回答

收藏

结合使用UNNEST和JOIN

技术问答 技术问答 175 人阅读 | 0 人回复 | 2023-09-14

我希望能够unnest有很多JOINs的复杂SQL查询中使用PostgreSQL中函数。这是查询示例:, L2 S6 K( z# X% l, M2 s+ c+ u$ T
SELECT 9 as keyword_id,COUNT(DISTINCT mentions.id) as total,tags.parent_id as tag_idFROM mentionsINNER JOIN taggings ON taggings.mention_id = mentions.idINNER JOIN tags ON tags.id = taggings.tag_idWHERE mentions.taglist && ARRAY[9] AND mentions.search_id = 3GROUP BY tags.parent_id我想在taggings因为我的mentions有一个表叫 taglist*    的 整数数组
' r5 }3 a" X! }1 O) U+ x, P- ^所有链接的字段,字段tag id组成。
*mentions" C3 y; u( }& [# X" B
我尝试了以下操作:3 f" F1 I4 l, q. N) N
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该方法有效,但结果不同于第一个查询。! S) m4 H4 t5 _1 }' O& \& V
所以我要做的是SELECT unnest(taglist)在JOIN查询中使用的结果用于补偿taggings表。
# G+ {5 ]( ?1 _0 z: ?1 d$ a我怎样才能做到这一点?
: d9 @" Q9 \+ Z9 V! c! g8 CUPDATE:    taglist以及提到的标记ID列表相同。6 z: z" f0 L6 s  T
                                                               
6 U. `, J' M) n9 \5 F    解决方案:                                                                0 H8 q4 V' G* J. c0 k
                                                                从技术上讲,您的查询可能是这样工作的(查询目标无法完全确定):( [: _: v; U1 F$ U* s  b' d% [
SELECT 9 AS keyword_id,count(DISTINCT m.id) AS total,t.parent_id AS tag_idFROM  (    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并保留标准化的数据库架构。然后,您的原始查询应该能够很好地服务,只使用别名缩短语法:
( I+ @7 `1 `! ^/ T7 ESELECT 9 AS keyword_id,count(DISTINCT m.id) AS total,t.parent_id AS tag_idFROM   mentions mJOIN   taggings mt ON mt.mention_id = m.idJOIN   tags     t  ON t.id = mt.tag_idWHERE  9 = ANY (m.taglist)AND    m.search_id = 3GROUP  BY t.parent_id;解开谜团 你不同结果的根本原因是不幸的命名协议,这是一些 具有挑战性的知识ORM    强加给人。  F% I4 S- Y5 B" s3 ~
我说的** ~~id~~** 是列名。不要在有多个表的数据库中使用这种反模式。是的,这基本上意味着 任何1 c4 M- j8 P0 X  Y, L" Z3 j6 U
数据库。一旦添加了一堆表(这就是你在数据库中 所做    ),你最终会得到一堆名字id。毫无意义。
& t& Q* N" B- c, Q名为表的ID列tag应为 tag_id    (除非有另一个描述性名称)。永远不要。id。3 {( k* Y$ Z6 A9 ^$ p. r
您的查询无意中计数,tags而不是mentions:
# p; a* q* |1 z* h" E: T! @6 V: [SELECT 25 AS keyword_id,count(m.id) AS total,t.parent_id AS tag_idFROM  (    SELECT unnest(m.taglist) AS id    FROM   mentions m    WHERE  m.search_id = 4    AND    25 = ANY (m.taglist)   ) mJOIN   tags t USING (id)GROUP  BY t.parent_id;它应该这样工作:0 z& d7 e: Z; V, p% }( C9 ?* p
SELECT 25 AS keyword_id,count( **DISTINCT** m.id) AS total,t.parent_idFROM  (    SELECT **m.id** ,unnest(m.taglist) **AS tag_id**    FROM   mentions m    WHERE  m.search_id = 4    AND    25 = ANY (m.taglist)   ) mJOIN   tags t **ON t.id =  m.tag_id**GROUP  BY t.parent_id;我还DISTINCT向您添加count()在查询过程中迷路。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则