简体   繁体   中英

How to merge one to many in left join where right have multiple rows to single row

Hi so i'm using leftjoin for two tables one is ordered_products and other is ordered_product_option

Ordered_produts table:-

 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  _id   |  name
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

   1    Track Pants
   2    PT tshirt

ordered_product_options table:-

  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  _id   |  ordered_produts_id | name  | value_name
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

   110    1                    size      32
   111    1                    color     yellow
   112    2                    size      25

My query:-

$this->orderProduct->leftjoin('ordered_product_options', 'ordered_products._id', '=', 'ordered_product_options.ordered_products__id')
                      ->join('orders', 'ordered_products.orders__id', '=', 'orders._id')

                        ->select(

                    'ordered_products._id as _id',
                    'ordered_products.price as total_amount',
                    'ordered_products.name as product_name',
                    'ordered_product_options.name as option name',
                    'ordered_product_options.value_name as option_value' 

                )->get()->toArray();

Result:-

      431 => array:5 [▼
    "_id" => 665
    "total_amount" => 300.0
    "product_name" => "PT TSHIRT"
    "option name" => "Size"
    "option_value" => "30"
  ]
  432 => array:5 [▼
    "_id" => 665
    "total_amount" => 300.0
    "product_name" => "PT TSHIRT"
    "option name" => "Color"
    "option_value" => "Yellow"
  ]

Result I want:-

 431 => array:5 [▼
    "_id" => 665
    "total_amount" => 300.0
    "product_name" => "PT TSHIRT"
    "option name" => "Size","color"
    "option_value" => "30","yellow"
  ]

Please Help Thanks in Advace

Consider the following, which represents one popular approach when working with an EAV:

DROP TABLE IF EXISTS products;

CREATE TABLE products
(product_id SERIAL PRIMARY KEY
,name VARCHAR(20) NOT NULL UNIQUE
);

INSERT INTO products VALUES
(1,'Track Pants'),
(2,'PT tshirt');

DROP TABLE IF EXISTS product_options;

CREATE TABLE product_options
(product_id INT NOT NULL
,attribute VARCHAR(12) NOT NULL
,value VARCHAR(12) NOT NULL
,PRIMARY KEY(product_id,attribute)
);

INSERT INTO product_options VALUES
(1,'size',32),
(1,'color','yellow'),
(2,'size',25);

SELECT p.*
     , MAX(CASE WHEN po.attribute = 'color' THEN value END) color
     , MAX(CASE WHEN attribute = 'size' THEN value END) size 
  FROM products p 
  LEFT 
  JOIN product_options po 
    ON po.product_id = p.product_id 
 GROUP 
    BY p.product_id;
+------------+-------------+--------+------+
| product_id | name        | color  | size |
+------------+-------------+--------+------+
|          1 | Track Pants | yellow | 32   |
|          2 | PT tshirt   | NULL   | 25   |
+------------+-------------+--------+------+

That said, there's nothing wrong with multiple LEFT JOINs; indeed it can be fractionally faster:

SELECT p.*
     , color.value color
     , size.value size
  FROM products p
  LEFT 
  JOIN product_options color
    ON color.product_id = p.product_id
   AND color.attribute = 'color'
  LEFT 
  JOIN product_options size
    ON size.product_id = p.product_id
   AND size.attribute = 'size';

   +------------+-------------+--------+------+
   | product_id | name        | color  | size |
   +------------+-------------+--------+------+
   |          1 | Track Pants | yellow | 32   |
   |          2 | PT tshirt   | NULL   | 25   |
   +------------+-------------+--------+------+

Also, although not universally popular, if using an EAV, I like to split the attributes out into separate tables according to data type, so you have a table of integer type things, and a table of string type things.

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