简体   繁体   English

如何在多对多关系中加入表?

[英]How to join table in many-to-many relationship?

Here is a simplified version of my problem.这是我的问题的简化版本。 I have two tables.我有两张桌子。 Each table has a unique ID field, but it's irrelevant in this case.每个表都有一个唯一的 ID 字段,但在这种情况下无关紧要。

shipments has 3 fields: shipment_id , receive_by_datetime , and qty . shipments有 3 个字段: shipment_idreceive_by_datetimeqty

deliveries has 4 fields: delivery_id , shipment_id , delivered_on_datetime , and qty . deliveries有 4 个字段: delivery_idshipment_iddelivered_on_datetimeqty

In shipments , the shipment_id and receive_by_datetime fields always match up.shipments中, shipment_idreceive_by_datetime字段始终匹配。 There are many rows in the table that would appear to be duplicates based off of those two columns (but they aren't... other fields are different).根据这两列,表中有许多行似乎是重复的(但它们不是……其他字段不同)。

In deliveries , the shipment_id matches up to the shipments table.deliveries中, shipment_idshipments表相匹配。 There are also many rows that would appear to be duplicates based off of the delivery_id and delivered_on_datetime fields (but they aren't again... other fields exist that I didn't list).根据delivery_iddelivered_on_datetime字段,还有许多行似乎是重复的(但它们不再是......其他字段存在我没有列出)。

I am trying to pull one row per aggregate delivered_on_datetime and receive_by_datetime , but because of the many-to-many relationships, it's difficult.我试图为每个聚合的delivered_on_datetimereceive_by_datetime拉一行,但由于多对多关系,这很困难。 Is a query somewhere along these lines correct?沿着这些路线的某处查询是否正确?

SELECT d.delivered_on_datetime, s.receive_by_datetime, SUM(d.qty)
FROM deliveries d
LEFT JOIN (
  SELECT DISTINCT s1.shipment_id, s1.receive_by_datetime
  FROM shipments s1
) s ON (s.shipment_id = d.shipment_id)
GROUP BY d.delivered_on_datetime, s.receive_by_datetime

You will run into problems where the total SUM(d.qty) will be larger than the value from SELECT SUM(qty) FROM deliveries您将遇到总SUM(d.qty)大于SELECT SUM(qty) FROM deliveries的值的问题

Something like this might be better suited for you:像这样的东西可能更适合你:

SELECT d.delivered_on_datetime, s.receive_by_datetime, SUM(d.qty) AS delivered_qty, SUM(d.qty) AS shipped_qty
FROM deliveries d
LEFT JOIN (
  SELECT s1.shipment_id, s1.receive_by_datetime, SUM(s1.qty) AS qty
  FROM shipments s1
  GROUP BY s1.shipment_id, s1.received_by_datetime
) s ON (s.shipment_id = d.shipment_id)
GROUP BY d.delivered_on_datetime, s.receive_by_datetime

If you somehow have (or might have) a shipment_id that has multiple values for received_by_datetime and it's best practice to assume that something else might have corrupted the data slightly then to prevent the lines in the deliveries table being duplicated while still returning a valid result you can use:如果您以某种方式拥有(或可能拥有)一个有多个值的deliveriesreceived_by_datetime并且最好假设其他东西可能会稍微损坏数据,然后防止shipment_id表中的行被重复,同时仍然返回一个有效的结果你可以使用:

SELECT d.delivered_on_datetime, s.receive_by_datetime, SUM(d.qty) AS delivered_qty, SUM(d.qty) AS shipped_qty
FROM deliveries d
LEFT JOIN (
  SELECT s1.shipment_id, MAX(s1.receive_by_datetime) AS receive_by_datetime, SUM(s1.qty) AS qty
  FROM shipments s1
  GROUP BY s1.shipment_id
) s ON (s.shipment_id = d.shipment_id)
GROUP BY d.delivered_on_datetime, s.receive_by_datetime

Yep, the problem with many-to-many is you get the cartesian product of rows, so you end up counting the same row more than once.是的,多对多的问题是你得到了行的笛卡尔积,所以你最终会多次计算同一行。 Once for each other row it matches against.它匹配的每一行都匹配一次。

In shipments, the shipment_id and receive_by_datetime fields always match up在货件中,shipping_id 和 receive_by_datetime 字段始终匹配

If this means there cannot be two shipments with the same ID but different dates then your query will work.如果这意味着不能有两个货件具有相同的 ID 但不同的日期,那么您的查询将有效。 But in general it is not safe.但总的来说,它并不安全。 ie If subselect distinct could return more than one row per shipment ID, you will be subject to the double counting issue.即,如果 subselect distinct 可能为每个货件 ID 返回多于一行,您将面临重复计数问题。 Generically this is a very tricky problem to solve - in fact I see no way it could be with this data model.一般来说,这是一个非常棘手的问题要解决 - 事实上,我认为这个数据 model 不可能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM