Как присоединиться к столу в отношениях «многие ко многим»? - PullRequest
0 голосов
/ 12 июля 2011

Вот упрощенная версия моей проблемы.У меня есть две таблицы.Каждая таблица имеет уникальное поле идентификатора, но в данном случае оно не имеет значения.

shipments имеет 3 поля: shipment_id, receive_by_datetime и qty.

deliveries имеет 4 поля: delivery_id, shipment_id, delivered_on_datetime и qty.

В shipments, shipment_id и receive_by_datetime поля всегда совпадают.В таблице есть много строк, которые выглядят как дубликаты, основанные на этих двух столбцах (но они не ... другие поля отличаются).

В deliveries, shipment_id соответствуетдо таблицы shipments.Есть также много строк, которые могут показаться дубликатами, основанными на полях delivery_id и delivered_on_datetime (но это не так ... существуют другие поля, которые я не перечислил).

Я пытаюсь вытащить по одной строке на агрегат delivered_on_datetime и receive_by_datetime, но из-за отношений "многие ко многим" это сложно.Является ли запрос где-то в этом направлении правильным?

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

Ответы [ 2 ]

2 голосов
/ 12 июля 2011

Вы столкнетесь с проблемами, когда сумма SUM(d.qty) будет больше, чем значение из SELECT SUM(qty) FROM deliveries

Что-то вроде этого может быть лучше для вас:

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

Еслиу вас каким-то образом есть (или может быть) shipment_id, который имеет несколько значений для received_by_datetime, и лучше всего предположить, что что-то еще могло немного повредить данные, чтобы предотвратить дублирование строк в таблице deliveries, пока они ещевозвращая действительный результат вы можете использовать:

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
1 голос
/ 12 июля 2011

Да, проблема со многими ко многим заключается в том, что вы получаете декартово произведение рядов, так что вы в конечном итоге считаете одну и ту же строку более одного раза.Один раз для каждой строки, с которой оно совпадает.

В отправлениях поля shipment_id и receive_by_datetime всегда совпадают

Если это означает, что не может быть двух отправлений с одинаковым идентификаторомно разные даты, тогда ваш запрос будет работать.Но в целом это не безопасно.т. е. если отдельный выбор может возвратить более одной строки для каждого идентификатора отправления, вы столкнетесь с проблемой двойного счета.В общем, это очень сложная проблема для решения - на самом деле я не вижу, как это могло бы быть с этой моделью данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...