【问题标题】:Joining three tables with primary in the middle连接三个中间的表
【发布时间】:2018-04-17 08:40:18
【问题描述】:

我对加入三张桌子感到头疼。我重新创建了一个简单的测试用例,在其中看到了同样的问题,所以看起来我在连接查询中犯了一个根本性错误:

我有三张桌子:

case:
id (PK)| date_closed
155    | '2018-04-17 10:08' 
156    | '2018-03-17 10:08'     
pizza  | '2018-02-17 10:08' 

registration:
id (FK) | source | quantity
155     | market | 300
155     | sawdust| 200

bagged:
id | case_id (FK) | kg_bagged
X  | 155          | 123
Y  | 155          | 90

我想加入这些表格来比较数量列和 kg_bagged 中每个“案例”的总金额。所以 case 表与其他两个表有 1:* many 的关系。因此我做了一个这样的连接查询:

SELECT case.id, 
       date_closed,
       SUM(quantity),
       SUM(kg_bagged),
       SUM(kg_bagged)/SUM(quantity) AS reduction_factor
FROM case
    JOIN bagged ON case.id = bagged.case_id
    JOIN registration ON case.id = registration.id

我认为这将是一个正确的查询,但 Postgres 告诉我必须将 case.id, date_closed 添加到 group by 子句。所以我添加了这个:

GROUP BY case.id, date_closed;

此代码运行时没有错误,但在案例 155 处显示的数量为 1000,而不是预期的 500 (200+300)。仅当有超过 1 条记录时才会出现此行为。当仅将 1 个表加入案例表时,它也可以正常工作。有人可以看到在 JOIN 查询中犯的错误吗?

我也尝试使用子查询来连接两个表,而不是在左侧表上使用连接,但它给了我类似的结果

【问题讨论】:

  • 它会导致连接到另外 2 个表上的 2 行的笛卡尔效应,总共创建 4 行。 (将您的预期答案从 500 加倍到 1000)

标签: sql postgresql join


【解决方案1】:

当您将 2 个其他表上的 2 行数据连接在一起时,它会匹配在一起,因此您会得到相乘的结果。在你的例子中是 2*2 = 4

为了更容易理解,在你执行查询时

 SELECT case.id, date_closed, source, quantity, kg_bagged
   FROM case
   JOIN registration ON registration.id = case.id
   JOIN bagged ON bagged.case_id = case.id

你会得到这样的数据:

| id  | date_closed        | source | quantity | kg_bagged |
| :-: | :----------------: | :----: | :------: | :-------: |
| 155 | '2018-04-17 10:08' | market | 300      | 123       |
| 155 | '2018-04-17 10:08' | sawdust| 200      | 123       |
| 155 | '2018-04-17 10:08' | market | 300      | 90        |
| 155 | '2018-04-17 10:08' | sawdust| 200      | 90        |

在这种情况下,根据我之前的经验,我曾经先编写子查询,先获取总和数据,然后再将它们连接在一起。

如:

   WITH r AS (SELECT id, sum(quantity) as quantity FROM registration GROUP BY id),
    b as (SELECT case_id, SUM(kg_bagged) as kg_bagged FROM bagged GROUP BY case_id)
 SELECT case.id, 
    date_closed,
    quantity,
    kg_bagged,
    kg_bagged/quantity AS reduction_factor
   FROM case
   JOIN b ON case.id = b.case_id
   JOIN r ON case.id = r.id

希望这个答案会对你有所帮助。

【讨论】:

  • 是的,这个解决方案有效。谢谢。虽然我还是不明白结果成倍增长的原因。我将不得不对此进行更多研究。感谢 Andrew,在笛卡尔效应的名称下有很多关于这个主题的资源。
  • @JosE 我已更新答案以获取有关此重复案例的更多信息。希望它能帮助你更容易理解。
  • 啊,是的,感谢您的更新。我现在看到了错误,它为每个可能的组合提供了一行。
猜你喜欢
  • 1970-01-01
  • 2012-03-06
  • 2018-11-22
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多