【问题标题】:SUM CASE LEFT JOIN output gives wrong sumSUM CASE LEFT JOIN 输出给出错误的总和
【发布时间】:2019-04-10 14:57:46
【问题描述】:

我有多个左连接,我需要聚合和非规范化数据 如图所示,我得到了 3 FA 的总和,而不是 F 的 1 FA。

示例:https://rextester.com/FOO264444

SELECT 
SUM(CASE WHEN fa.PFId=1111 and fa.AcId=2 THEN 1 ELSE 0 END) as conditionalcountall

FROM #Fan f
LEFT JOIN #PF pf
    ON pf.FId = f.Id
LEFT JOIN #LPe lip
    ON lip.Id = pf.PId
LEFT JOIN #FA fa
    ON fa.PFId = pf.Id
LEFT JOIN #Ac a
    ON a.Id = fa.AcId
LEFT JOIN #DelAc das
    ON das.PFId = pf.Id
LEFT JOIN #DAc da
    ON da.Id = das.DAId

-------------------------   
id |conditionalcountall |
-------------------------
  1          3          |
-------------------------

当我删除最后 2 个左连接时,它会给出所需的输出 1。但我需要这 2 个连接来聚合这 2 个表中的其他数据。

SELECT 
    SUM(CASE WHEN fa.ProfileFanId=1111 and fa.ActivityId=2 THEN 1 ELSE 0 END) as conditionalcountall

    FROM #Fan f
    LEFT JOIN #ProfileFan pf
        ON pf.FanId = f.Id
    LEFT JOIN #LinkedInProfile lip
        ON lip.Id = pf.ProfileId
    LEFT JOIN #FanActivity fa
        ON fa.ProfileFanId = pf.Id
    LEFT JOIN #Activity a
        ON a.Id = fa.ActivityId

id |conditionalcountall |
-------------------------
 1 |             1      |
-------------------------

我做错了什么?

【问题讨论】:

  • 这是一个常见的错误,人们希望加入一些聚合(每个都可能涉及加入),但他们错误地尝试先进行所有的加入,然后再进行所有的聚合。这是一个常见问题解答。在考虑发布之前,请始终在谷歌上搜索您的错误消息或您的问题/问题/目标的许多清晰、简洁和准确的措辞,有或没有您的特定字符串/名称,并阅读许多答案。如果您发布问题,请使用一个短语作为标题。请参阅How to Ask 和投票箭头鼠标悬停文本。
  • 当您只需要对来自 FanActivity 表的两个字段进行求和时,为什么要在连接中使用所有表?您的数据是多余的,这就是它返回正确总和 3 的原因
  • 您提供minimal reproducible example 代码很好,但请将其作为文本放在您的问题中,而不仅仅是一个链接——让您的帖子自成一体。为了使其“最小化”,包括您可以提供的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)您需要“聚合其他数据”,但您不需要“需要这 2 个连接”——它为您提供了一个无用的表。如果您查看部分结果,您可能会看到。您的 MCVE 实际上并没有告诉我们您希望结果中的哪些行。另外,写出来可能会让你看到你需要子查询。

标签: sql-server sum left-join case


【解决方案1】:

你可以借助不同的逻辑得到你想要的结果。 对于你给定的场景,你可以通过改变你的情况来实现这一点

SELECT  COUNT(DISTINCT 
             CASE WHEN fa.PFId=1111 and fa.AId=2 
                  THEN CAST(fa.PFId AS VARCHAR) + '-' + CAST(fa.ActivityId AS VARCHAR) 
             ELSE NULL END
        ) as conditionalcountall

在这种逻辑情况下,当设置一个包含所需字段组合的字符串时,当条件绕过设置为 null 时,因为我们知道 count 子句不计算 null 字段,并且在 distinct 的帮助下,你得到 1 而不是 3

【讨论】:

    【解决方案2】:

    #DeliveryActions 和 #DA 在连接中必须包含多行。如果您只关心它是否存在一次,则必须对这些表中的数据进行分组。

    --替换这个

    LEFT JOIN #DA das
        ON das.PFId = pf.Id
    LEFT JOIN #DA da
        ON da.Id = das.DAId
    

    --有了这个

    LEFT JOIN (SELECT PFId
                FROM #DA ia
                LEFT JOIN #DA ib
                ON ia.DAId = ib.Id
                GROUP BY PFId) das
                ON das.PFId = pf.Id
    

    请注意,因为您在任何地方都使用 LEFT JOIN,但其他任何表中都可能有 0 行?不确定这是否是你所追求的。如果您需要它存在于所有表中的计数,只需将 LEFT JOIN 更改为 INNER JOIN (如果像我一样懒惰,则为 JOIN)

    【讨论】:

    • 好的,所以最后 2 个连接需要分组为一个具有单个 ID 的子查询。我会编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 2020-08-27
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多