【问题标题】:MS Access query with multiple joins returning duplicate rows具有多个连接的 MS Access 查询返回重复行
【发布时间】:2016-10-18 12:20:33
【问题描述】:

我正在使用 Access 查询包含乘客信息的多个表。我已经能够将其提炼成我认为导致问题的原因,但我不确定如何解决它。

基本上是三个表:

乘客

ID   | PASSENGER_NAME | COST_CENTER
-------------------------------------
1    | John Wright    | 31231       
2    | Cheryl Brown   | 54555       
3    | Adam Yang      | 65655       

FARE_LEVEL

ID   | TICKET_NUMBER  | PASSENGER_NAME | TICKET_AMT | IS_REFUND
---------------------------------------------------------------
1    | 14325435       | John Wright    | $632.64    | 0    
2    | 46746745       | Adam Yang      | $797.32    | 0  
3    | 45354434       | Cheryl Brown   | $2331.00   | 0  
4    | 67876456       | Cheryl Brown   | $990.11    | 0     
5    | 34654546       | Adam Yang      | $552.71    | 0  
6    | 14325435       | John Wright    | -$632.64   | 1    
7    | 87989879       | John Wright    | $123.11    | 0  
8    | 99124324       | Adam Yang      | $1114.42   | 0  
9    | 77231235       | Adam Yang      | $6232.32   | 0 

INCENTIVE_LOG

ID   | PASSENGER_NAME | INCENTIVE_AMT
-------------------------------------
1    | Adam Yang      | $1000.00       
2    | Cheryl Brown   | $1000.00       
3    | John Wright    | $1000.00   
4    | John Wright    | $1000.00       
5    | John Wright    | $1000.00   

我正在使用这个查询来加入他们:

SELECT
PASSENGERS.PASSENGER_NAME,
Sum(FARE_LEVEL.TICKET_AMT) AS SumOfFARES,
Count(INCENTIVE_LOG.INCENTIVE) AS CountOfINCENTIVE,
Sum(INCENTIVE_LOG.INCENTIVE) AS SumOfINCENTIVE
FROM (PASSENGERS LEFT OUTER JOIN FARE_LEVEL ON PASSENGERS.PASSENGER_NAME = FARE_LEVEL.PASSENGER_NAME)
INNER JOIN INCENTIVE_LOG ON PASSENGERS.PASSENGER_NAME = INCENTIVE_LOG.PASSENGER_NAME
GROUP BY PASSENGERS.PASSENGER_NAME;

我要查找的结果是 PASSENGER 表中每位乘客的所有票价总和,以及 PASSENGER 表中每位乘客的所有奖励总和。所以对于“约翰·赖特”,我希望看到

PASSENGER_NAME | SumOfFares | CountOfIncentive | SumOfIncentive
---------------------------------------------------------------
John Wright    | $123.11    | 3                | $3000.00   

相反,我得到的结果似乎是重复计算的。当我将 GROUP BY 更改为

GROUP BY PASSENGERS.PASSENGER_NAME, INCENTIVE_LOG.ID, FARE_LEVEL.ID;

我可以看到它汇总错误的所有重复行。它似乎为与乘客对应的 FARE_LEVEL 和 INCENTIVE 行的每个组合创建一行,因此如果有人有 7 种票价和 3 种奖励,它将创建 21 行。

我相当确定问题出在我的加入中,但我不知道如何解决它。

编辑: 我能够通过在原始查询中创建两个子查询来解决这个问题

SELECT
    PASSENGERS.PASSENGER_NAME,
    Sum(Query4.SumOfTICKET_AMT) AS SumOfFARES,
    Sum(Query2.SumOfINCENTIVE) AS Incentive
FROM (PASSENGERS 
    LEFT OUTER JOIN (
        SELECT PASSENGERS.PASSENGER_NAME, Sum(FARE_LEVEL.TICKET_AMT) AS SumOfTICKET_AMT
        FROM PASSENGERS LEFT OUTER JOIN FARE_LEVEL ON PASSENGERS.PASSENGER_NAME = FARE_LEVEL.PASSENGER_NAME
        GROUP BY PASSENGERS.PASSENGER_NAME 
    ) AS Query4
    ON PASSENGERS.PASSENGER_NAME = Query4.PASSENGER_NAME)
    INNER JOIN (
        SELECT PASSENGERS.PASSENGER_NAME, Sum(INCENTIVE_LOG.INCENTIVE) AS SumOfINCENTIVE
        FROM PASSENGERS LEFT OUTER JOIN INCENTIVE_LOG ON PASSENGERS.PASSENGER_NAME = INCENTIVE_LOG.PASSENGER_NAME
        GROUP BY PASSENGERS.PASSENGER_NAME
    ) AS Query2
    ON PASSENGERS.PASSENGER_NAME = Query2.PASSENGER_NAME
GROUP BY PASSENGERS.PASSENGER_NAME;

【问题讨论】:

  • ID字段是关键字段吗?您的问题似乎更像是表设计问题而不是查询问题。为什么要链接Passengers_name 而不是ID 字段?表之间的 ID 也不匹配,即...Joen Wright 在 PASSSENGERS 中的 ID = 1,在 FARE_LEVEL 中的 ID = 1, 6,7 和在 INCENTIVE_LOG 中的 2, 3
  • ID 字段是每个表的键,每行自动生成。在表格中,我正在寻找将奖励和票价与个人联系起来的唯一方法是通过 PASSENGER_NAME
  • 我认为这确实是问题所在,它是一个表格设计问题。 ID 可能应该为Passenger 表而不是其他表自动编号。这样键将在表之间匹配。不过,您的查询看起来不错
  • 我无法更改 FARE_LEVEL 和 INCENTIVE_LOG 表的结构,但我不确定匹配的 ID 与 PASSENGERS 表中的匹配名称有何不同?它仍然会遇到我认为的相同问题
  • 那么你的关键字段的目的是什么?

标签: sql ms-access join duplicates


【解决方案1】:

你必须先总结激励措施:

SELECT PASSENGERS.PASSENGER_NAME,
     Count(INCENTIVE_LOG.INCENTIVE) AS CountOfINCENTIVE,
     Sum(INCENTIVE_LOG.INCENTIVE) AS SumOfINCENTIVE
FROM (select PASSENGERS.PASSENGER_NAME, 
           Sum(FARE_LEVEL.TICKET_AMT) AS SumOfFARES
      From PASSENGERS 
           LEFT OUTER JOIN FARE_LEVEL 
                ON PASSENGERS.PASSENGER_NAME = FARE_LEVEL.PASSENGER_NAME
      Group by PASSENGERS.PASSENGER_NAME
      ) x
     INNER JOIN INCENTIVE_LOG 
          ON x.PASSENGER_NAME = INCENTIVE_LOG.PASSENGER_NAME
GROUP BY PASSENGERS.PASSENGER_NAME;

此外,您可以创建一个仅计算总激励的第一个查询,然后在此摘要中使用该查询。

【讨论】:

  • 这是有道理的,但是当我尝试使用您的查询版本时,我收到错误“您的查询不包含指定的表达式“PASSENGER_NAME”作为聚合函数的一部分。
  • 我听取了您的建议并创建了两个查询来获得总奖励(和票价),然后将它们合并为一个,现在它返回了正确的结果;我在主帖中包含了这个查询
  • 对不起,我在子查询版本中错过了 group by。刚才加进去了。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 2023-04-07
  • 2016-04-11
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
相关资源
最近更新 更多