【问题标题】:SQL Server Query aggregating incorrectly when no where or having clause present当没有 where 或有子句存在时,SQL Server 查询聚合不正确
【发布时间】:2021-02-07 01:08:34
【问题描述】:

编辑:我已经尝试了前两种解决方案,但是在查看带有 WHERE 子句的单个客户时,仍然遇到查询返回正确结果的问题,但对于没有它的同一客户则不正确。这怎么可能发生?可能导致这种情况的幕后情况是什么?

我正在构建一个查询以在一张大表上加入和聚合客户信息,因此我开始使用 where 子句为单个客户构建查询,以确保逻辑在对客户群实施之前有效.

我加入的表格如下所示:

表 A:

| customer | order_id |
----------------------
| abc      | 1       |
| abc      | 2       |
| xyz      | 3       |
| xyz      | 4       |
| xyz      | 5       |
| xyz      | 6       |
...

表 B:

| order_id | return_date   |
----------------------------
| 1        |       Mon     |
| 3        |       Tues    |
| 5        |       Wed     |
...

我需要按客户名称汇总这些信息,并从本质上计算他们的信息出现在每个表中的次数。

所以查询看起来像这样:

SELECT 
  a.customer as customer_name
  ,COUNT(DISTINCT(a.order_id)) as total_orders
  ,COUNT(DISTINCT(B.order_id)) as num_returns
FROM B

RIGHT JOIN (
  SELECT 
    customer
    order_id
  FROM A
  ) as a

ON B.order_id = a.order_id
WHERE customer = 'xyz'
GROUP BY a.customer

当存在 where 子句时,这非常有效(也适用于 group by 之后的 HAVING customer = 'xyz')但是当我删除 where 子句以将其应用于客户群时,结果完全不正确.我怎样才能解决这个问题以便为大众服务?

【问题讨论】:

    标签: sql sql-server group-by aggregate-functions where-clause


    【解决方案1】:

    我建议在 bleft join 上进行预聚合:

    select a.customer, count(*) total_orders, coalesce(sum(b.num_returns), 0) num_returns
    from a
    left join (
        select order_id, count(*) num_returns
        from b
        group by order_id
    ) b on b.order_id = a.order_id
    group by a.customer
    

    无论是否使用where 子句,结果都是一致的。请注意,这假定a 中没有重复的(customer_id, order_id),如您的示例数据所示。

    横向连接也可以:

    select a.customer, count(*) total_orders, sum(b.num_returns) num_returns
    from a
    cross apply (
        select count(*) num_returns
        from b
        where b.order_id = a.order_id
    ) b
    group by a.customer
    

    【讨论】:

      【解决方案2】:

      这个查询应该可以工作:

      SELECT a.customer as customer_name,
             COUNT(DISTINCT a.order_id) as total_orders,
             COUNT(DISTINCT B.order_id) as num_returns
      FROM A LEFT JOIN
           B
           ON B.order_id = a.order_id
      WHERE a.customer = 'xyz'
      GROUP BY a.customer;
      

      如果xyzA 中没有行,那么这将不返回任何行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多