使用左连接和不同的总和不正确的值

Posted

技术标签:

【中文标题】使用左连接和不同的总和不正确的值【英文标题】:Using left join and distinct sums incorrect values 【发布时间】:2021-03-18 20:19:39 【问题描述】:

我有这个 SQL 查询:

SELECT
    COUNT(DISTINCT [sb].[UserId]) AS NumberOfCustomers, 
    SUM([sb].[ProbabilityAlive]) AS ProbabilityAlive
FROM
    sb  
WHERE  
    sb.[Date] = '03/11/2020 00:00:00' 
    AND sb.[ClientId] = '1112'

此查询返回:

NumberOfCustomers: 50280
ProbabilityAlive: 26107.6830

我最近添加了另一个表,当使用左连接或连接时,我得到的存活概率总和不正确:

SELECT
    COUNT(DISTINCT [dbo].[sb].[UserId]) AS NumberOfCustomers, 
    SUM([dbo].[sb].[ProbabilityAlive]) AS ProbabilityAlive,
    SUM([dbo].[AdditionalClvData].[PeakClv]) AS PeakClv
FROM
    sb  
LEFT JOIN 
    [dbo].[AdditionalClvData] ON [dbo].[AdditionalClvData].UserId = [dbo].[sb].UserId  
 WHERE  
     sb.[CalculationDate] = '03/11/2020 00:00:00' 
     AND sb[ClientId] = '2' 

这个查询现在返回这个结果:

NumberOfCustomers: 50280
ProbabilityAlive: 76949.2354
PeakClv: 44835004.95810

ProbabilityAlive 几乎是原来的三倍。使用左连接时不应该得到相同的总和吗?

【问题讨论】:

我删除了 mysql 标签,因为代码显然是 SQL Server。此外,样本数据和期望的结果也会有所帮助。 为什么数字变了?因为表之间是1:M的关系。所以不,你的期望是不正确的。先求和/计数,然后加入。 如果您删除 distinct 和 aggregation 函数,您可能会发现您的外连接并没有按照您认为的方式进行操作。在聚合之前,我会确保您的查询返回您想要的记录。 Distinct 可能会给您一种温暖模糊的感觉,认为它是正确的,但它也可以隐藏“我正在检索表中的每条记录” FYI 3 列的部分命名将被弃用,应避免使用。为您的对象提供别名并使用这些别名限定您的列。 【参考方案1】:

我建议在子查询中预先聚合:

SELECT 
    COUNT(*) AS NumberOfCustomers, 
    SUM(s.ProbabilityAlive) AS ProbabilityAlive,
    SUM(a.PeakClv) as PeakClv
FROM (
    SELECT [UserId], SUM([sb].[ProbabilityAlive]) AS ProbabilityAlive
    FROM sb  
    WHERE sb.[Date] = '20200311'
    GROUP BY [UserId]
) s
LEFT JOIN (
    SELECT [UserId], SUM([PeakClv]) as PeakClv
    FROM [dbo].[AdditionalClvData]
    GROUP BY [UserId]
) a ON a.[UserId] = s.[UserId]

【讨论】:

以上是关于使用左连接和不同的总和不正确的值的主要内容,如果未能解决你的问题,请参考以下文章

Spark 使用左外连接给出不正确的结果

我怎样才能做一个不同的总和?

MySQL 上的左连接 + 计数 + 总和

在左连接中选择取决于另一个表中字段总和的行?

查找从三个表的左连接获得的三列的总和

左连接给出不正确的结果