Search code examples
mysqljoinone-to-manygroup-concat

Categorize the identical rows without repeating one-to-many relationship using LEFT JOIN


pardon my question title, I'm not sure what should I put it, I have these two tables as below.

products                orders
+------+----------+     +--------+------+-------+
|  id  | name     |     |   id   |  qty |  pid  |
+------+----------+     +--------+------+-------+
|  1   | mouse    |     | 10001  |  20  |   1   |
|  2   | keyboard |     | 10002  |  15  |   3   |
|  3   | headset  |     | 10004  |  5   |   3   |
+------+----------+     | 10005  |  12  |   2   | 
                        | 10006  |  18  |   1   |
                        +--------+------+-------+

This is the LEFT JOIN query I am using and the output

SELECT p.id AS No, p.name AS ProductName, o.qty AS Quantity
FROM products AS p
LEFT JOIN orders AS o ON p.id = o.pid

+------+-------------+----------+
|  No  | ProductName | Quantity |
+------+-------------+----------+
|  1   | mouse       |   20     |
|  1   | mouse       |   18     |
|  2   | keyboard    |   12     | 
|  3   | headset     |   15     |
|  3   | headset     |    5     |
+------+-------------+----------+

What I am trying to achieve is an output as below:

+------+-------------+----------+
|  No  | ProductName | Quantity |
+------+-------------+----------+
|  1   | mouse       |   20     |
|      |             |   18     |
|  2   | keyboard    |   12     | 
|  3   | headset     |   15     |
|      |             |    5     |
+------+-------------+----------+

My question is it possible to do so? Any reply and suggestions is greatly appreciate. Thanks.

P/S: I also have tried using the GROUP_CONCAT(qty SEPARATOR ",") but it returns the result in one row as I may have more additional column to add in the Orders table in the future and it will be difficult to read.


Solution

  • In this case you can use MySQL variables. I store the previous product id in the variable @prev, and only if it changes we output the product name.

    http://www.sqlfiddle.com/#!2/d5fd6/9

    SET @prev := NULL;
    
    SELECT
      IF( @prev = p.id, NULL, p.id) AS No,
      IF( @prev = p.id, NULL, p.name) AS ProductName,
      o.qty AS Quantity
     ,@prev := p.id
    
    FROM products AS p
    
    LEFT JOIN orders AS o
           ON p.id = o.pid