Выбрать только совпадающие записи из двух объектов - PullRequest
0 голосов
/ 20 января 2020

Пожалуйста, помогите мне с запросом MYSQL.

Имя объекта: OrderItem Атрибуты: orderId (PK), orderItemSeqId (PK), productId

Имя объекта: ProductFacility Атрибуты :ilityId ( PK), productId (PK), inventoryCount (целое число)

**OrderId  | orderItemSeqId | productId**

  OID1     |       0001     |   10000 

  OID1     |       0002     |   10001 

  OID1     |       0003     |   10002


**FacilityId | ProductId | InventoryCount**

  FC_1     |   10000    |    12

  FC_1     |   10001    |    5

  FC_1     |   10002    |    7

  FC_2     |   10001    |    1

  FC_2     |   10002    |    6

  FC_3     |   10002    |    7

Здесь я хочу получить объект (FC_1), в котором есть все продукты, доступные для заказа.

Мне не нужны записи объекта, в которых есть частичные продукты (например, у объекта FC_3 есть только один (10002) продукт из OID1 заказа)

Мне нужны только записи объекта, в которых есть все продукты из заказа (например, OID1)

ВАЖНАЯ ТОЧКА: Этот SQL будет выполнен для миллионов записей.

Ответы [ 4 ]

0 голосов
/ 20 января 2020

Это должно работать:

select oc.orderId, ofc.facilityId
from
(
   select orderId, count(*) productCount
   from OrderItem
   group by orderId) oc 
inner join
(
   select pf.facilityId, oi.orderId, count(*) productsAvailableCount
   from ProductFacility pf
   inner join OrderItem oi on oi.productId = pf.productId and pf.inventoryCount > 0
   group by pf.facilityId, oi.orderId
) ofc on ofc.orderId = oc.orderId and oc.productCount = ofc.productsAvailableCount

Демонстрация на DB Fiddle

0 голосов
/ 20 января 2020

Это обеспечит вам необходимые услуги

with cte as
(
 select OrderId, count(*)      as c
 from orderT a
 group by OrderId
)
select FacilityId, b.OrderId, count(*) as c from Facility a
inner join orderT b on a.ProductId  = b.ProductId
group by FacilityId, b.OrderId
having count(*) = (select c from cte c where c.OrderId = b.OrderId)
0 голосов
/ 20 января 2020

Чтобы получить список объектов, которые могут удовлетворить заказ, вам нужно проверить, в каком объекте есть InventoryCount > 0 для каждого продукта в заказе, что вы можете сделать с помощью этого запроса:

SELECT O.OrderId, F.FacilityID
FROM (SELECT DISTINCT productId
      FROM OrderItem) P
CROSS JOIN (SELECT DISTINCT OrderId
            FROM OrderItem) O
CROSS JOIN (SELECT DISTINCT FacilityId
            FROM ProductFacility) F
LEFT JOIN OrderItem OI ON OI.OrderId = O.OrderID AND OI.productId = P.productId
LEFT JOIN ProductFacility PF ON PF.FacilityId = F.FacilityId AND PF.productId = OI.productId AND PF.InventoryCount > 0
GROUP BY O.OrderId, F.FacilityID
HAVING COUNT(OI.ProductId) = COUNT(PF.ProductId)

I добавили дополнительный заказ к моей демонстрации, для которого требуются продукты 10001 и 10002; для этого вывод

OrderId     FacilityID
OID1        FC_1
OID2        FC_1
OID2        FC_2

Демонстрация на SQLFiddle

0 голосов
/ 20 января 2020

Попробуйте это:

select * 
from ProductFacility  f1
where (select count(distinct InventoryCount) cnt_fac
       from ProductFacility  f2
       where f2.FacilityId = f1.FacilityId
       and InventoryCount > 0
       group by FacilityId ) = (select count(distinct productId) 
                                from OrderItem );

Вот это ДЕМО

...