PIVOT - Group Duplicate Records in a Single Line

Asked

Viewed 3,762 times

5

I have a problem with a query, in which I need to turn rows into columns. In case I thought to use the function pivot, but it didn’t work very well, since mysql doesn’t provide me with such a function. But the tables are as follows::

Tabela pedidos_lojas

inserir a descrição da imagem aqui

inserir a descrição da imagem aqui

inserir a descrição da imagem aqui

My goal is to display the results as follows inserir a descrição da imagem aqui

However my query is a little awkward, because it returns the same products in different lines and ae can not display this way, even trying to group the columns.

SELECT pq.id_produto,pd.descricao,
       CASE WHEN pl.id_loja = '1' THEN pq.produto_quantidade
       END LOJA1,
       CASE WHEN pl.id_loja = '2' THEN pq.produto_quantidade
       END LOJA2,
       CASE WHEN pl.id_loja = '3' THEN pq.produto_quantidade
       END LOJA3,
       CASE WHEN pl.id_loja = '4' THEN pq.produto_quantidade
       END LOJA4
FROM pedidos_produtos_quantidade pq
LEFT JOIN pedidos_lojas pl ON pl.id = pq.id_pedido_loja
LEFT JOIN lojas l ON pl.id_loja = l.id
LEFT JOIN produtos pd ON pq.id_produto = pd.id_produto
GROUP BY pd.descricao,
         pq.produto_quantidade

This sql generates this result, which I cannot group in the way I mentioned: inserir a descrição da imagem aqui

Someone could help me make this cluster?

  • Have you thought about using sub querys? It loses performance but in your case I think it fits well..

  • Actually mysql provides the pivot function yes, you would have to create a precedent.

  • You have to use SUM(pq.produto_quantidade) as LOJA1 to make the sum correctly.

  • something like: IF(pl.id_loja = 1, SUM(pq.produto_quantidade), 0) as QUANT_LOJA1.

  • Another thing, watch out for left join, for the left join brings everything that is similar in the second table... and in case you want to join some fields, then... for some cases, you should use the inner join... look at that picture.

  • @Ivanferrer even with the IF and the sums the records are repedtidos, the Inner Join I entered and did not change the result

  • @Igormonteiro may be that the subquery helps, but I still don’t know how to do it to give me a result next to the last image I sent

  • 1

    tries to query the colleague below by playing the result in a temp table. After that it gives a group by in the columns you want to group by putting a sum.. I think it works

Show 3 more comments

1 answer

3


Using the following structure:

CREATE TABLE pedidos_lojas(`id` integer, `id_loja` integer);
CREATE TABLE pedidos_produtos_quantidade(`id` integer, `id_produto` integer, `produto_quantidade` integer, `id_pedido_loja` integer);
CREATE TABLE produtos(`id_produto` integer, `descricao` varchar(100));
CREATE TABLE lojas(`id` integer, `nome` varchar(100));

INSERT INTO pedidos_lojas(`id`, `id_loja`)
VALUES (1, 2),
       (11, 3),
       (12, 4);

INSERT INTO pedidos_produtos_quantidade(`id`, `id_produto`, `produto_quantidade`, `id_pedido_loja`)
VALUES (1, 1, 10, 1),
       (2, 2, 20, 1),
       (12, 1, 15, 11),
       (13, 38, 18, 1),
       (14, 44, 12 ,1),
       (15, 44, 22, 11),
       (16, 44, 10, 12),
       (17, 38, 9, 11),
       (18, 38, 29, 12),
       (19, 1, 15, 12),
       (20, 2, 18, 11);

INSERT INTO produtos(`id_produto`, `descricao`)
VALUES (1, 'Abacate'),
       (2, 'Abacaxi'),
       (38, 'Laranja'),
       (44, 'Manga');

INSERT INTO lojas(`id`, `nome`)
VALUES (1, 'Centro'),
       (2, 'Lagoa'),
       (3, 'Gloria'),
       (4, 'Serra');

Use the following query:

SELECT pq.id_produto,
       pd.descricao,
       sum(CASE pl.id_loja WHEN 1 THEN pq.produto_quantidade ELSE 0 END) as loja1,
       sum(CASE pl.id_loja WHEN 2 THEN pq.produto_quantidade ELSE 0 END) as loja2,
       sum(CASE pl.id_loja WHEN 3 THEN pq.produto_quantidade ELSE 0 END) as loja3,
       sum(CASE pl.id_loja WHEN 4 THEN pq.produto_quantidade ELSE 0 END) as loja4
  FROM pedidos_produtos_quantidade pq
  LEFT JOIN pedidos_lojas pl ON pl.id = pq.id_pedido_loja
  LEFT JOIN lojas l ON pl.id_loja = l.id
  LEFT JOIN produtos pd ON pq.id_produto = pd.id_produto
 GROUP BY pq.id_produto,
          pd.descricao;

Resulting in:

| id_produto | descricao | loja1 | loja2 | loja3 | loja4 |
| ---------- | --------- | ----- | ----- | ----- | ----- |
| 1          | Abacate   | 0     | 10    | 15    | 15    |
| 2          | Abacaxi   | 0     | 20    | 18    | 0     |
| 38         | Laranja   | 0     | 18    | 9     | 29    |
| 44         | Manga     | 0     | 12    | 22    | 10    |

In the query described above we group the data by id of the product and describe a column for each store, checking the code of the same in a CASE within the SUM.


See working on DB Fiddle.

  • Friend, thanks for the help, but your result was the same as mine, the products still appear repeated

  • Can you post the image of how the result was with this select? Depending on how the fields looked just add a "distinct" right after the "select" clause"

  • It was the same as the last image I posted, even using distinct

  • 1

    @tkmattos, fixed the "group by" and tested with the informed data. Now it seems to be correct.

  • Perfect @Sorack excellent indeed!!!

  • would know how to explain why you used the expression sum(pq.produto_quantity*(1-abs(Sign(pl.id_store-1)))) ???

  • Explanation added as per the article used as basis

  • 1

    @Tkmattos, is a calculation that uses sum() - summing up, * multiplication, - subtraction, abs() - absolute value and sign() - inversion of the signal.

  • thanks for the explanations @Ivanferrer

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.