img: DALL·E 2024-08-09 07.00.00 - A high-quality image showcasing a detailed SQL query being written in a code editor, such as VS Code, on a dark theme background....
## Como Criar Relatórios de Cotações com Dados Agrupados Usando SQL
Quando trabalhamos com sistemas ERP e precisamos gerar relatórios de cotações que apresentam dados de múltiplos fornecedores, é comum encontrarmos a necessidade de pivotar registros que, originalmente, são apresentados de forma vertical. Isso é especialmente útil quando o objetivo é comparar preços ou condições de diferentes fornecedores para um mesmo produto em uma única linha do relatório.
Neste artigo, vamos explorar uma abordagem para transformar registros verticais em colunas, facilitando a impressão de relatórios que consolidam informações de vários fornecedores em uma única linha. Vamos utilizar SQL com técnicas de pivotagem, e ao final, mostraremos como estender essa técnica para um número variável de fornecedores.
### Estrutura do Relatório
Vamos imaginar um relatório que precise apresentar dados como na tabela abaixo:
```plaintext
+------------------------------------------------+-----------+----------------------+----------------------+----------------------+----------------------+
| |fornecedor:| FORNECEDOR 1 | FORNECEDOR 2 | FORNECEDOR 3 | FORNECEDOR 4 |
| +-----------+----------------------+----------------------+----------------------+----------------------+
| |contato: | CONTATO FORNECEDOR 1 | CONTATO FORNECEDOR 2 | CONTATO FORNECEDOR 3 | CONTATO FORNECEDOR 4 |
| +-----------+----------------------+----------------------+----------------------+----------------------+
| |Codigo: | 000001 | 000002 | 000003 | 000004 |
+--------+-----------------------------+---------+------+----+------------+---------+------------+---------+------------+---------+------------+---------+
| codigo | descrição produto | armazem | qtd. | un | vlr. unit. | subtotal| vlr. unit. | subtotal| vlr. unit. | subtotal| vlr. unit. | subtotal|
+--------+-----------------------------+---------+------+----+------------+---------+------------+---------+------------+---------+------------+---------+
|00000001|PRODUTO 00000001 | 01 | 10 | UN | 10,00| 100,00| 15,00| 150,00| 11,50| 115,00| 10,01| 100,10|
+--------+-----------------------------+---------+------+----+------------+---------+------------+---------+------------+---------+------------+---------+
```
No entanto, os dados podem estar armazenados em um formato vertical:
```plaintext
+--------+-----------------------------+------+------------+-------+-----+--+-------+--------+
|codpro |descricao |codfor|fornecedor |armazem|qtd |un|vlrunit|subtotal|
+--------+-----------------------------+------+------------+-------+-----+--+-------+--------+
|00000001|PRODUTO 00000001 |000001|FORNECEDOR 1|01 |10.00|UN| 10.00| 100.00|
|00000002|PRODUTO 00000002 |000002|FORNECEDOR 2|01 |10.00|TN| 10.00| 100.00|
|00000003|PRODUTO 00000003 |000003|FORNECEDOR 3|02 |10.00|MT| 10.00| 100.00|
|00000004|PRODUTO 00000004 |000004|FORNECEDOR 4|01 |10.00|LT| 10.00| 100.00|
+--------+-----------------------------+------+------------+-------+-----+--+-------+--------+
```
### Solução: Usando Pivot para Transpor Registros
Para transformar a estrutura vertical em uma apresentação horizontal, podemos utilizar a técnica de `PIVOT` no SQL, criando uma consulta que agrupa os dados por produto e distribui as informações dos fornecedores em colunas distintas.
#### Passo 1: Preparando os Dados
Primeiro, vamos criar uma tabela temporária usando uma Common Table Expression (CTE) para ordenar os fornecedores:
```sql
WITH SC8_ROW AS (
SELECT
SC8.C8_NUM,
SC8.C8_PRODUTO,
SB1.B1_DESC,
SB1.B1_LOCPAD,
SC8.C8_QUANT,
SC8.C8_UM,
SC8.C8_PRECO,
SC8.C8_TOTAL,
SC8.C8_FORNECE,
SC8.C8_LOJA,
ROW_NUMBER() OVER (PARTITION BY SC8.C8_NUM, SC8.C8_PRODUTO ORDER BY SC8.C8_FORNECE, SC8.C8_LOJA) AS FornecedorRow
FROM
SC8010 SC8
LEFT JOIN
SB1010 SB1 ON SB1.B1_COD = SC8.C8_PRODUTO
WHERE
SC8.D_E_L_E_T_ = ' '
AND SB1.D_E_L_E_T_ = ' '
)
```
Aqui, `ROW_NUMBER` é usado para gerar um número sequencial para cada fornecedor, dentro do mesmo produto. Este número será usado para dividir os fornecedores em diferentes colunas.
#### Passo 2: Criando a Tabela Pivotada
Agora, podemos usar a técnica de pivotagem para transformar as linhas em colunas:
```sql
SELECT
C8_NUM,
C8_PRODUTO,
B1_DESC,
B1_LOCPAD,
C8_QUANT,
C8_UM,
MAX(CASE WHEN FornecedorRow = 1 THEN C8_FORNECE ELSE '' END) AS COD_FOR1,
MAX(CASE WHEN FornecedorRow = 1 THEN C8_PRECO ELSE 0 END) AS VUNIT_FOR1,
MAX(CASE WHEN FornecedorRow = 1 THEN C8_TOTAL ELSE 0 END) AS VTOT_FOR1,
MAX(CASE WHEN FornecedorRow = 2 THEN C8_FORNECE ELSE '' END) AS COD_FOR2,
MAX(CASE WHEN FornecedorRow = 2 THEN C8_PRECO ELSE 0 END) AS VUNIT_FOR2,
MAX(CASE WHEN FornecedorRow = 2 THEN C8_TOTAL ELSE 0 END) AS VTOT_FOR2,
MAX(CASE WHEN FornecedorRow = 3 THEN C8_FORNECE ELSE '' END) AS COD_FOR3,
MAX(CASE WHEN FornecedorRow = 3 THEN C8_PRECO ELSE 0 END) AS VUNIT_FOR3,
MAX(CASE WHEN FornecedorRow = 3 THEN C8_TOTAL ELSE 0 END) AS VTOT_FOR3,
MAX(CASE WHEN FornecedorRow = 4 THEN C8_FORNECE ELSE '' END) AS COD_FOR4,
MAX(CASE WHEN FornecedorRow = 4 THEN C8_PRECO ELSE 0 END) AS VUNIT_FOR4,
MAX(CASE WHEN FornecedorRow = 4 THEN C8_TOTAL ELSE 0 END) AS VTOT_FOR4
FROM
SC8_ROW
GROUP BY
C8_NUM,
C8_PRODUTO,
B1_DESC,
B1_LOCPAD,
C8_QUANT,
C8_UM
```
Aqui, utilizamos `MAX` em conjunto com `CASE` para selecionar as informações de cada fornecedor, transformando as linhas em colunas.
#### Passo 3: Lidando com Mais de Quatro Fornecedores
Se houver mais de quatro fornecedores, podemos estender o relatório com uma consulta adicional utilizando `UNION ALL`:
```sql
UNION ALL
SELECT
C8_NUM,
C8_PRODUTO,
B1_DESC,
B1_LOCPAD,
C8_QUANT,
C8_UM,
MAX(CASE WHEN FornecedorRow = 5 THEN C8_FORNECE ELSE '' END) AS COD_FOR1,
MAX(CASE WHEN FornecedorRow = 5 THEN C8_PRECO ELSE 0 END) AS VUNIT_FOR1,
MAX(CASE WHEN FornecedorRow = 5 THEN C8_TOTAL ELSE 0 END) AS VTOT_FOR1,
-- Repita para FornecedorRow 6, 7, 8
FROM
SC8_ROW
WHERE
FornecedorRow > 4 AND FornecedorRow <= 8
GROUP BY
C8_NUM,
C8_PRODUTO,
B1_DESC,
B1_LOCPAD,
C8_QUANT,
C8_UM
```
### Conclusão
Com esta técnica, você pode transformar dados verticalmente estruturados em um relatório que apresenta as informações de forma comparativa e horizontal, facilitando a análise de cotações. A capacidade de estender o número de fornecedores utilizando `UNION ALL` garante que sua solução seja escalável, independentemente da quantidade de dados que você precise manipular.
Essa abordagem pode ser adaptada e aplicada em diferentes contextos dentro do SQL, dependendo das necessidades do seu negócio.
Comentários
Postar um comentário