【问题标题】:Introducing third table as left join duplicates values引入第三个表作为左连接重复值
【发布时间】:2020-08-04 23:36:55
【问题描述】:

如何设置此左连接,使其不会重复我在 Table2 中的调用或在 Table3 中的销售?

左加入表 2 或表 3 返回准确的答案,左加入同一查询重复 - 虽然我有 3 个电话和 444 美元的销售额,但它返回 6 个电话(表 2 的三个记录 x 表 3 的两个记录) 和 1332 美元的销售额。

使用 SQL Server Studio 17。

CREATE TABLE #Table1 (
    CommercialTime datetime,
    NextCommercialTime datetime,
    Station varchar(4),
    Cost int    )
INSERT INTO #Table1 (
    CommercialTime,
    NextCommercialTime,
    Station,
    Cost    )
VALUES
(   '2020-04-06 12:01:00.000',
    '2020-04-06 12:15:00.000',
    'ZZZZ',
    '9999'  )

CREATE TABLE #Table2 (
    CallTime datetime,
    Station varchar(4),
    CallCount int   )
INSERT INTO #Table2 (
    CallTime,
    Station,
    CallCount   )
VALUES
(   '2020-04-06 12:02:00.000',
    'ZZZZ',
    '1' ),
(   '2020-04-06 12:05:00.000',
    'ZZZZ',
    '1' ),
(   '2020-04-06 12:07:00.000',
    'ZZZZ',
    '1' )

CREATE TABLE #Table3 (
    SaleTime datetime,
    Station varchar(4),
    SaleAmount int  )
INSERT INTO #Table3 (
    SaleTime,
    Station,
    SaleAmount  )
VALUES
(   '2020-04-06 12:04:00.000',
    'ZZZZ',
    '123'   ),
(   '2020-04-06 12:07:00.000',
    'ZZZZ',
    '321'   )

SELECT 
          one.Station
        , SUM(two.Callcount) as Calls
        , SUM(three.SaleAmount) as Sales
    FROM #Table1 one WITH(NOLOCK)
    LEFT JOIN #Table2 two   WITH(NOLOCK)    ON one.Station = two.Station 
                                                AND two.CallTime between one.CommercialTime and one.NextCommercialTime      
    LEFT JOIN #Table3 three WITH(NOLOCK)    ON one.Station = three.Station 
                                                AND three.SaleTime between one.CommercialTime and one.NextCommercialTime    
    GROUP BY one.Station

--Output:
    Station Calls   Sales
    ZZZZ    6   1332

【问题讨论】:

  • 这是一个常见的错误,人们想要一些连接,每个可能涉及不同的键,一些子查询,每个可能涉及连接和/或聚合,但他们错误地尝试完成所有连接然后全部聚合或聚合以前的聚合。在适当的行上写单独的总和和/或总结一个案例语句选择行;加入常见的唯一列集。 PS 在minimal reproducible example 中:找到第一个子表达式,它是您可以显示的代码执行您期望的扩展,而代码不符合您的期望。然后解释你的期望和原因。
  • 这是一个常见问题解答。在考虑发布之前,请阅读手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:stackoverflow.com 和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。请参阅How to Ask 和投票箭头鼠标悬停文本。除非我们努力(重新重新)写清楚,否则我们无法推理、交流或搜索。
  • @DonnaC 以下任何一个答案对您有帮助吗?作为新人,你读过Accepting Answers吗?

标签: sql sql-server join left-join


【解决方案1】:

对于这个问题,我建议使用子查询而不是连接,例如

SELECT 
  one.Station
  , (
    select sum(CallCount)
    from #Table2 two
    where one.Station = two.Station 
    AND two.CallTime between one.CommercialTime and one.NextCommercialTime
  ) Calls
  , (
    select sum(SaleAmount)
    from #Table3 three
    where one.Station = three.Station 
    AND three.SaleTime between one.CommercialTime and one.NextCommercialTime
  ) Sales
FROM #Table1 one

原因是连接为您提供了您不想要的所有行组合。解释一下,当您将 Table2 加入 Table1 时,您会得到 3 行:

Station TwoCallTime
ZZZZ    2020-04-06 12:02:00.000
ZZZZ    2020-04-06 12:05:00.000
ZZZZ    2020-04-06 12:07:00.000

那么当你加入有 2 行的 Table3 时,你现在有 6 行:

Station TwoCallTime             ThreeCallTime
ZZZZ    2020-04-06 12:02:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:02:00.000 2020-04-06 12:07:00.000
ZZZZ    2020-04-06 12:05:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:05:00.000 2020-04-06 12:07:00.000
ZZZZ    2020-04-06 12:07:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:07:00.000 2020-04-06 12:07:00.000

这不是您在这里想要完成的。

【讨论】:

    【解决方案2】:

    您可以使用outer apply

    SELECT one.Station, ISNULL(t2.calls, 0) AS Calls, ISNULL(t3.sales, 0) AS Sales
    FROM #Table1 one WITH(NOLOCK) OUTER APPLY
         ( SELECT SUM(two.Callcount) as calls
           FROM #Table2 two
           WHERE one.Station = two.Station AND 
                 two.CallTime between one.CommercialTime and one.NextCommercialTime      
         ) t2 OUTER APPLY
         ( SELECT SUM(three.SaleAmount) as sales
            FROM #Table3 three
            WHERE one.Station = three.Station AND 
                  three.SaleTime between one.CommercialTime and one.NextCommercialTime    
         ) t3;
    

    【讨论】:

    • 您认为使用子查询更好还是不同
    • @DaleK。 . .在这种情况下,如果它使用OUTER APPLY,这将等同于使用子查询(事实上,如果两个表中都没有匹配,它会过滤掉行)。但是,横向连接比子查询强大得多。有些人更喜欢将表引用保留在FROM 子句中,而不是分散在整个查询中。在这个问题的上下文中,子查询更准确,因为问题明确提到了LEFT JOINs。
    猜你喜欢
    • 2018-06-01
    • 2018-11-06
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    相关资源
    最近更新 更多