SQL-запрос, включающий сравнение множеств - PullRequest
0 голосов
/ 28 июня 2019

Фон

Продукты можно продавать в пачках. Присутствуют следующие таблицы: products, bundles, bundles_products, orders, orders_products.

Можно сказать, что заказ «содержит» пакет, если он содержит все продукты пакета.

Задача

Как можно посчитать заказы на связки?

Пример

продукты стол

id  name
1   broom
2   mug
3   spoon
4   candle

связки стол

id  name
1   dining
2   witchcraft

bundles_products таблица

bundle_id product_id
1         2
1         3
2         1
2         4

orders_products table

order_id  product_id
1000      1
1000      3
1001      1
1001      2
1001      3

Запрос вернет следующую таблицу:

bundle     orders
dining     1
witchcraft 0

Примечания

В примере намеренно пропущена таблица orders, так как она не относится к тому, что в ней содержится.

Конечно, к этому можно было бы обязательно обратиться, написав некоторый код и собрав данные, но я надеялся, что существует декларативный SQL-способ запросов для такого рода вещей?

Одна из идей, которые у меня возникли, состояла в том, чтобы использовать GROUP_CONCAT, чтобы объединить все продукты пакета и как-то сравнить его с продуктами каждого заказа. Тем не менее, далеко не ясно.

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Один из способов - использовать две Производные таблицы (подзапросы).В первом подзапросе мы получим общее количество уникальных продуктов для каждого пакета.Во втором подзапросе мы получим все продукты в заказе для комбинации заказа и пакета.

Мы будем LEFT JOIN их на bundle_id, а также сопоставим общее количество продуктов в пакете.в них.В конце концов, мы сделаем группировку по пакетам и посчитаем количество подходящих заказов.

SELECT dt1.id              AS bundle_id,
       dt1.name            AS bundle,
       Count(dt2.order_id) AS orders
FROM   (SELECT b.id,
               b.name,
               Count(DISTINCT bp.product_id) AS total_bundle_products
        FROM   bundles AS b
               JOIN bundles_products AS bp
                 ON bp.bundle_id = b.id
        GROUP  BY b.id,
                  b.name) AS dt1
       LEFT JOIN (SELECT op.order_id,
                         bp.bundle_id,
                         Count(DISTINCT op.product_id) AS order_bundle_products
                  FROM   orders_products AS op
                         JOIN bundles_products AS bp
                           ON bp.product_id = op.product_id
                  GROUP  BY bp.bundle_id,
                            op.order_id) AS dt2
              ON dt2.bundle_id = dt1.id
                 AND dt2.order_bundle_products = dt1.total_bundle_products
GROUP  BY dt1.id,
          dt1.name 

SQL Fiddle DEMO

0 голосов
/ 28 июня 2019

Вот краткий пример, в котором отсутствуют некоторые части, которые я пропустил, поскольку не знаю точной структуры базы данных.Логика такова:

  1. Сформирована временная таблица, которая состоит из 3 строк - заказ, количество товаров, связанных с комплектом, количество товаров в комплекте
  2. Затем мы выбираем только заказы изэта таблица, в которой у нас есть последние две переменные, равные
select count(order_id) from orders 
    left join(
        select count(*) from bundles_products as bundle_amount, 
                  sum(case when orders_products in (
                  select names from bundles_products where bundle_id='1') then 1 else 0) as order_total, 
                  orders.order_id 
            left join product on bundle_products.product_id = products.product_id
            left join orders on products.product_id = orders_products.product_id
        where bundle_products.bundle_id ='1'
        ) as my_table 
        on orders.order_name = my_table.orders 
        where my_table.bundle_amount = my_table.order_total

Редактировать: я разместил это как ответ на предыдущую версию вопроса, без подробного объяснения.

Edit2:немного исправил запрос.Это может быть отправной точкой.Логика все та же, вы можете получить количество заказов для каждого bundle_id, используя ее

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