【问题标题】:SQL Aggregate Functions -- HAVING vs WHERESQL 聚合函数 -- HAVING 与 WHERE
【发布时间】:2019-08-08 22:41:54
【问题描述】:

上下文:我在SQLFiddle Postgres 9.6 中摆弄 SQL。我正在尝试将聚合函数应用于外部查询中的 2 列,这些列依赖于子查询中值的存在。

我很难确定使用 WHERE 子句而不是 HAVING 查询是否正确。SQL 执行但我不确定它是否会生成预期的结果。

问题:有人可以帮助我了解这是否是执行聚合的正确方法吗?如果不是,如果在外部查询中包含 HAVING 需要 GROUPING BY user_id ,我该如何修改查询以获得预期的结果,这有点违背了目的。

预期结果:我想计算用户在进行新操作之前执行的操作数。如果用户 (user_id) 进入下一个操作 (View Product),我只想计算 Read Article 事件的数量,我将使用聚合来计算一些平均值。

示例输出:

查询:

SELECT event_type as action_a,
       COUNT(event_type) as action_a_count,
       COUNT(DISTINCT user_id) as unique_users
FROM events 
WHERE event_type in ('Read Article')
AND user_id in 
  (
    SELECT DISTINCT(user_id) as user_id 
    FROM events
    WHERE event_type in ('View Product')
  )
GROUP BY event_type

【问题讨论】:

  • 您没有解释预期结果或提供示例数据以及您希望从该数据中获得的输出。当您不解释您打算做什么时,很难说您是否正确地做事。你可能也会混淆一些事情。 HAVING 通常在与 WHERE 聚合之后使用,以进一步减少结果集。考虑计算在一段时间内订购了某种产品的客户的订单数量(WHERE 和 GROUP BY),然后只查看购买了 100 件或更多的订单(HAVING SUM() >= 100)。
  • 旁注:(1) event_type 是“阅读文章”,即不为空。所以COUNT(event_type) 只是应该计算行数而不是event_type 的出现次数不为空。请改用COUNT(*),这正是为了做到这一点:计算行数。 (2) DISTINCT 不是函数。所以,DISTINCT(user_id)应该是DISTINCT user_id。无论如何,在IN 子句中,您不必使用DISTINCT。甚至建议不要这样做。不要告诉 DBMS 如何工作,只要说你想要那个集合中的用户 ID 就足够了:AND user_id in (SELECT user_id FROM events ......
  • (3)user_id as user_id 当然是多余的。 (4)event_type in ('View Product') 可以写成event_type = 'View Product' 你可能知道。

标签: sql postgresql aggregate-functions


【解决方案1】:

您的查询很好。使用WHERE event_type = 'Read Article' 过滤事件行。因此,只有那些行必须被聚合。

您可以改用HAVING event_type = 'Read Article',因为您也是按该列分组的。这意味着您将首先为 all 行查找用户,然后聚合所有需要的用户行,然后才关闭不需要的 event_types。这将使 DBMS 有更多的工作要做。

结论:使用WHERE 尽快减少行数,这样DBMS 可以处理更小的数据集。这将加快您的查询速度。

【讨论】:

    【解决方案2】:

    HAVING 和 WHERE 看起来确实有重叠,但也有区别,WHERE 检查行是否相等,而 HAVING 用于检查聚合集,最基本的示例是在带有 a 的表中查找重复项

    SELECT column_name, count(*)
    FROM table_name
    GROUP BY column_name
    HAVING count(*) > 1
    

    此查询需要在过滤之前计算行数,因此使用 HAVING。在您的情况下,使用 WHERE 过滤相等性很好,因为它只需要考虑一行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 2014-02-24
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多