【问题标题】:How do I do this without a subquery?如何在没有子查询的情况下做到这一点?
【发布时间】:2020-10-21 06:21:33
【问题描述】:

SELECT COUNT(*) FROM org_type_on_related_genre 
WHERE genre_id = :deletedGenreId 
and org_type_id IN 
(SELECT org_type_id 
 FROM org_type_on_related_genre 
 GROUP BY org_type_id 
 HAVING count(*) > 1)

我需要进行相同的查询,但没有子查询!

我需要获取genre_id 等于 :deletedGenreId 的行数,并且此表中该行的 org_type_id 值不是唯一的

【问题讨论】:

  • 为什么要去掉子查询?
  • 优化器应该根据表中的数据提出一个最适合您的查询的计划,因此您应该真正担心如何编写查询,除非您有其他一些我们没有的约束不知道。
  • 有人告诉我子查询的生产力很差。需要在没有子查询的情况下重做

标签: sql postgresql select count window-functions


【解决方案1】:

子查询没有错。如果操作正确,子查询实际上可以帮助提高性能并增加代码可读性。对于复杂的逻辑,它是必不可少的。

我们通常想要摆脱的是相关子查询,就像您脚本中的子查询一样。 以下查询实现了与您的相同的逻辑,但没有相关的子查询:

with dup_org_type as (
select org_type_id
  from org_type_on_related_genre
 group
    by org_type_id
having count(0) > 1 
)
select count(0)
  from org_type_on_related_genre otrg
      ,dup_org_type dup
 where otrg.genre_id = :deletedgenreid
   and otrg.org_type_id = dup.org_type_id

如果表很大,有很多不同的org_type_id,而deletedgenreid 是非常有选择性的,你的脚本实际上会有更好的性能。这完全取决于查询需要处理的数据量。

【讨论】:

    【解决方案2】:

    我怀疑在没有某种子查询或派生表的情况下可以有效地解决这个问题。

    这是一个仍然使用子查询的选项,但带有窗口函数。我希望这应该比您的原始查询更有效,因为该表只扫描一次(第二级查询更多的是语法糖):

    select count(*) 
    from (
        select count(*) over(partition by org_type_id) cnt
        from org_type_on_related_genre 
        where genre_id = :deletedgenreid 
    ) t
    where cnt > 1
    

    【讨论】:

    • @vage:请详细说明您所说的不起作用是什么意思。
    【解决方案3】:

    没有子查询?我认为你可以这样做:

    select count(*) over ()
    from org_type_on_related_genre 
    where genre_id = :deletedgenreid 
    group by org_type_id
    having count(*) > 1
    limit 1;
    

    不过,这似乎没什么用。

    Here 是一个 dbfiddle。

    【讨论】:

    • @vage 。 . .这有一个 dbfiddle 表明它确实工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 2023-03-14
    • 2019-01-18
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多