【问题标题】:SQL SERVER MULTIPLE JOIN: avoid duplicate valuesSQL SERVER MULTIPLE JOIN:避免重复值
【发布时间】:2016-08-04 10:37:02
【问题描述】:

我的数据库中有 3 个表:-

客户:

 CId | CName | CLocation | CJoinDate

付款:

TxnId | TxStatus | TxComment | TxAmount | CId | TxDate

约会:

AppId | AppCode | CId | ADate | AComment

当我对两个表进行左连接时,计算结果会正确。但是当我尝试加入 3 个表时,计算的结果是错误的。

例如:-

如果我尝试这个查询,那么计算的总金额是正确的:

SELECT c.CName, sum(p.TxAmount) 
FROM Customer c LEFT JOIN Payment p ON c.CId = p.CId 
WHERE p.TxStatus = 1 
GROUP BY c.CName;

在上面的查询中,我只是加入了两个表,这给了我正确的结果。

现在,当我想在一个表中显示所有记录时,我不得不加入 3 个表。 以下是我尝试过的查询:

SELECT c.CName as Name, sum(p.TxAmount) as Payment, count(distinct a.ADate) as Total_Visit 
FROM Customer c LEFT JOIN Payment p ON c.CId = p.CId LEFT JOIN Appointment a ON c.CId = a.CId
WHERE p.TxStatus = 1 
GROUP BY c.CName;

上面的查询给了我每个客户的错误付款金额。错误结果的原因是 Appointments 表与每个客户的 Payment 表相比具有更多的行。因此,为了显示所有约会条目,付款金额会重复,因为计算错误。

如何使用上述查询解决上述情况。

Tks

编辑:实际上还有 2-3 个表,我必须加入类似于 Appointment 表以​​及每个月的 GROUP BY 子句。

EDIT1:通过多个 CTE 修复它。感谢您的宝贵指点,它确实很有帮助。

【问题讨论】:

    标签: sql-server join


    【解决方案1】:

    如果您确定第一个查询正确计算了总和,请使用简单的 CTE 表达式

    WITH cte AS 
    (
    SELECT c.CName, c.CID, sum(p.TxAmount) AS sumAmount
    FROM Customer c LEFT JOIN Payment p ON c.CId = p.CId 
    WHERE p.TxStatus = 1 
    GROUP BY c.CName, c.CID 
    )
    SELECT cte.CName, cte.sumAmount, count(distinct a.ADate) as Total_Visit
    FROM cte LEFT JOIN Appointment a ON c.CId = a.CId
    GROUP BY c.CName, cte.sumAmount
    

    【讨论】:

      【解决方案2】:

      尝试使用子查询:

      SELECT 
      c.CName as Name
      , sum(p.TxAmount) as Payment
      , Total_Visit = (SELECT count(distinct a.ADate) FROM Appointment a ON c.CId = a.CId)
      FROM Customer c 
      LEFT JOIN Payment p ON c.CId = p.CId 
      WHERE p.TxStatus = 1 
      GROUP BY c.CName;
      

      【讨论】:

      • 其实我有多个表要加入。上述查询只是一个大问题的小问题。所以我想知道我们是否可以用 JOIN 来解决问题。
      • 好的,您也可以对其他表使用子查询。考虑使用子查询和 Pawel 的 CTE 变体编写查询。然后使用执行计划成本最低的那个?
      • 我们是否也可以使用 CTE 或带有 GROUP BY 子句的子查询,因为我已经显示了给定年份每个月的总数。
      • 当然,您可以按日期对其进行分组,但这取决于您希望如何排列行和列(逐年等)。
      【解决方案3】:

      您可以计算每个 CId 的 total_visit,然后加入子查询

      SELECT 
        c.CName as Name
      , sum(p.TxAmount) as Payment
      , Total_Visit 
      FROM Customer c 
      LEFT JOIN Payment p ON c.CId = p.CId 
      LEFT JOIN (SELECT a.CId, count(distinct a.ADate) Total_visit FROM Appointment a group by a.CId) as a on c.CId = a.CId 
      WHERE p.TxStatus = 1 
      GROUP BY c.CName;
      

      【讨论】:

        猜你喜欢
        • 2019-11-30
        • 1970-01-01
        • 2018-12-17
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        相关资源
        最近更新 更多