简体   繁体   中英

MYSQL How find order products matching current storage products (compare two tables for 100% match)

i'm looking for solution to check if multiple rows from one table have match in other table. In my situation i need to check if items from orders are in storage. Currently I use php to check orders - script is taking open orders and foreach one by one to check storage. It's generating quite a lot of queries and it's not efficient at all and i'm looking for solution to do this via sql query.

Desired result should be:

OrderId | Date       | Products 

1002/02 | 2020/08/16 | 1x Ipod; 2x battery; 9x some item;

0333/4  | 2020/06/22 | 10x shelf

Storage products table

id | id_product | quantity

Orders

id | reference | id_status | created_at

Order Products

Id | id_order | quantity | id_storage_product

在此处输入图像描述

I've written some code to generate table visible above but result it's not even close to desired.

select('orders.id', orders.created_at','orders.reference', 'storage_products.id as storageProductId')
                ->join('order_products', 'orders.id', '=', 'order_products.id_order')
                ->join('storage_products', 'order_products.id_product', '=', 'storage_products.id_product')
                ->where('storage_products.quantity', '>=', 'order_products.quantity')
                ->whereIn('orders.id_status', array(1, 2))  //get new orders/ open
                ->where('order_products.id_storage_product', null) 
                ->groupBy('orders.id');

Clean sql:

SELECT `orders`.`id`,
       `orders`.`created_at`,
       `orders`.`reference`,
       `storage_products`.`id` AS `storageProductId`,
       `order_products`.`id_order`
FROM   `orders`
       INNER JOIN `order_products`
               ON `orders`.`id` =
                  `order_products`.`id_order`
       INNER JOIN `storage_products`
               ON `order_products`.`id_product` =
                  `storage_products`.`id_product`
WHERE  `storage_products`.`quantity` >=
              'order_products.quantity'
       AND `orders`.`id_status` IN ( 1, 2 )
       AND `order_products`.`id_storage_product` IS NULL
GROUP  BY `orders`.`id`
ORDER  BY `orders`.`id` ASC

So code should find open orders (id_status); where storage quantity is equal or greater than product in order; where id_storage_products is null (means product bought on website but it was not in storage when ordered). Upper query result is wrong because it showed me partial match to storage - even without checking quantity (some products have 0 but still displayed).

For any help many thanks

EDIT: fiddle sample: https://www.db-fiddle.com/f/6jKvKXPYvsLeXgm3Qv1nHu/0

I tried the following query on the db-fiddle link and this works.

SELECT
    orders.reference, orders.created_at, order_products.id_product
FROM
    storage_products 
LEFT JOIN 
    order_products ON storage_products.id_product = order_products.id_product 
LEFT JOIN
    orders ON orders.id = order_products.id_order;

What I did in the query is calling all storage_products with the same id_product in order_products and proceed to call all orders in the called order_products.

Your query contains the condition:

AND `order_products`.`id_storage_product` IS NULL

but in your sample data all values are 0 .
So instead I use COALESCE() to cover both cases.
Also I removed the condition:

AND `orders`.`id_status` IN ( 1, 2 )

because the column id_status is not included in the definition of the table orders in your sample data.

This query works:

SELECT o.id,
       o.reference,
       o.created_at,
       GROUP_CONCAT(op.quantity, 'x', op.id_product separator ' ;') products
FROM orders o
INNER JOIN order_products op ON o.id = op.id_order
INNER JOIN storage_products sp ON op.id_product = sp.id_product
WHERE sp.quantity >= op.quantity AND COALESCE(op.id_storage_product, 0) = 0
GROUP  BY o.id, o.reference, o.created_at
ORDER  BY o.id ASC

See the demo .
Results:

| id  | reference | created_at          | products      |
| --- | --------- | ------------------- | ------------- |
| 2   | 345554/02 | 2020-08-22 00:00:00 | 3x188 ; 1x155 |

If you also join the table products (I assume there is such a table) you can get the names of the products instead of their ids.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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