简体   繁体   中英

How to fetch all the products from one table and merge one row from another table which contain multiple rows?

I have to tables. products table and product_variants table. In product table , I have

id, product_name, photo .

In product_variants table, I have

id, product_id, packet_size, price .

I have to add products first, then will add variants. It is possible that no variants have been added for that.

I want to fetch all the product with one variant details from variants table with the lowest price.

Example scenario:

products table

id    product_name     photo
1     product_1        1.png
2     product_2        2.png
3     product_3        3.png
4     product_4        4.png

product_variants

id     product_id      packet_size    price
1      1               100 ML         50 RS.
2      1               200 ML         100 Rs.
3      1               300 ML         150 RS.
4      2               300 L          300 Rs.
5      2               200 L          200 Rs.
6      3               200 K          200 Rs.

I want the result to be as below:

1     product_1        1.png     100 ML         50 RS.
2     product_2        2.png     200 L          200 Rs.
3     product_3        3.png     200 K          200 Rs.

Thanks.

Based on all the other questions your can find for "mysql join group min" or "mysql join group max" there are some catches when using GROUP BY and MIN/MAX and JOINs. You can use the following approach:

  1. SELECT (only) the min price of a variant for a given product.
  2. SELECT the remaining info of the found variant.
  3. SELECT the product info of the found variant.

For step 1 the query will look like this:

SELECT
    product_id,
    MIN(price) as price
FROM
    product_variants
GROUP BY
    product_id

This will result in the following output (ids may differ):

+------------+-------+
| product_id | price |
+------------+-------+
|          1 |    50 |
|          2 |   200 |
|          4 |   200 |
+------------+-------+

For step 2 we use this result in a JOIN query on itself:

SELECT
    v2.product_id,
    v2.packet_size,
    v2.price
FROM
    product_variants v2
JOIN
    (SELECT      -- here is your first query
         product_id,
         MIN(price) as price
     FROM
         product_variants
     GROUP BY
         product_id
    ) v1         -- notice the "v1" alias here, its needed
USING (product_id, price)

The result will be:

+------------+-------------+-------+
| product_id | packet_size | price |
+------------+-------------+-------+
|          1 | 100 ML      |    50 |
|          2 | 200 L       |   200 |
|          4 | 200 L       |   200 |
+------------+-------------+-------+

And for step 3 it's just a "normal" JOIN between two tables:

SELECT
    p.id,
    p.product_name,
    p.photo,
    v3.packet_size,
    v3.price
FROM
    products p
JOIN
    (SELECT    -- here is query 2
         v2.product_id,
         v2.packet_size,
         v2.price
     FROM
         product_variants v2
     JOIN
         (SELECT     -- here is query 1
              product_id,
              MIN(price) as price
          FROM
              product_variants
          GROUP BY product_id
         ) v1
     USING (product_id, price)
    ) v3
ON
    p.id = v3.product_id;

And this will get you the following result (again ids may differ):

+----+--------------+-------+-------------+-------+
| id | product_name | photo | packet_size | price |
+----+--------------+-------+-------------+-------+
|  1 | product_1    | 1.png | 100 ML      |    50 |
|  2 | product_2    | 2.png | 200 L       |   200 |
|  4 | product_3    | 3.png | 200 L       |   200 |
+----+--------------+-------+-------------+-------+

And if you use a LEFT JOIN instead of a "normal" JOIN, you get products as well which doesn't have any variants:

+----+--------------+-------+-------------+-------+
| id | product_name | photo | packet_size | price |
+----+--------------+-------+-------------+-------+
|  1 | product_1    | 1.png | 100 ML      |    50 |
|  2 | product_2    | 2.png | 200 L       |   200 |
|  4 | product_3    | 3.png | 200 L       |   200 |
|  5 | product_4    | 4.png | NULL        |  NULL |
+----+--------------+-------+-------------+-------+

The big catch is to fetch the remaining info of a found variant. You cannot do this in one query because the group function will fetch the correct value, but the other column values after the GROUP BY will not be from the found group function value, but instead will be most likely from the first row in the group.

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