Muitos analistas de dados se limitam às funções básicas do SQL como SELECT, JOIN, GROUP BY e WHERE. No entanto o SQL oferecem um arsenal de funções mais avançadas que podem simplificar consultas complexas e melhorar significativamente a performance. Neste tutorial, exploraremos essas funções usando exemplos práticos, tanto no MySQL quando no PostgreSQL.
Base de Dados de Exemplo
Para demonstrar essas funções, vamos criar um sistema de e-commerce simples com as seguintes tabelas:
-- Criação das tabelas de exemplo
CREATE TABLE categorias (
id INT PRIMARY KEY,
nome VARCHAR(100),
descricao TEXT
);
CREATE TABLE produtos (
id INT PRIMARY KEY,
nome VARCHAR(200),
preco DECIMAL(10,2),
categoria_id INT,
estoque INT,
data_criacao DATE,
ativo BOOLEAN
);
CREATE TABLE clientes (
id INT PRIMARY KEY,
nome VARCHAR(200),
email VARCHAR(150),
data_nascimento DATE,
cidade VARCHAR(100),
estado VARCHAR(50)
);
CREATE TABLE pedidos (
id INT PRIMARY KEY,
cliente_id INT,
data_pedido TIMESTAMP,
valor_total DECIMAL(10,2),
status VARCHAR(50)
);
CREATE TABLE itens_pedido (
id INT PRIMARY KEY,
pedido_id INT,
produto_id INT,
quantidade INT,
preco_unitario DECIMAL(10,2)
);
-- Inserção de dados de exemplo
INSERT INTO categorias VALUES
(1, 'Eletrônicos', 'Dispositivos eletrônicos'),
(2, 'Roupas', 'Vestuário em geral'),
(3, 'Livros', 'Literatura e educação'),
(4, 'Casa', 'Itens para casa');
INSERT INTO produtos VALUES
(1, 'Smartphone', 899.99, 1, 50, '2024-01-15', true),
(2, 'Laptop', 1299.99, 1, 30, '2024-01-20', true),
(3, 'Camiseta', 29.99, 2, 100, '2024-02-01', true),
(4, 'Livro SQL', 49.99, 3, 75, '2024-02-10', true),
(5, 'Mesa', 199.99, 4, 25, '2024-02-15', true);
INSERT INTO clientes VALUES
(1, 'João Silva', 'joao@email.com', '1985-05-15', 'São Paulo', 'SP'),
(2, 'Maria Santos', 'maria@email.com', '1990-08-22', 'Rio de Janeiro', 'RJ'),
(3, 'Pedro Costa', 'pedro@email.com', '1988-12-03', 'Belo Horizonte', 'MG');
INSERT INTO pedidos VALUES
(1, 1, '2024-03-01 10:30:00', 929.98, 'entregue'),
(2, 2, '2024-03-02 14:15:00', 1349.98, 'processando'),
(3, 1, '2024-03-03 09:45:00', 79.98, 'cancelado'),
(4, 3, '2024-03-04 16:20:00', 249.98, 'entregue');
INSERT INTO itens_pedido VALUES
(1, 1, 1, 1, 899.99),
(2, 1, 3, 1, 29.99),
(3, 2, 2, 1, 1299.99),
(4, 2, 4, 1, 49.99),
(5, 3, 3, 2, 29.99),
(6, 3, 4, 1, 49.99),
(7, 4, 5, 1, 199.99),
(8, 4, 4, 1, 49.99);
erDiagram
categorias {
int id PK
varchar nome
text descricao
}
produtos {
int id PK
varchar nome
decimal preco
int categoria_id FK
int estoque
date data_criacao
boolean ativo
}
clientes {
int id PK
varchar nome
varchar email
date data_nascimento
varchar cidade
varchar estado
}
pedidos {
int id PK
int cliente_id FK
timestamp data_pedido
decimal valor_total
varchar status
}
itens_pedido {
int id PK
int pedido_id FK
int produto_id FK
int quantidade
decimal preco_unitario
}
%% Relacionamentos
categorias ||--o{ produtos : "possui"
clientes ||--o{ pedidos : "faz"
pedidos ||--o{ itens_pedido : "contém"
produtos ||--o{ itens_pedido : "está em"Parte 1: Funções que Funcionam em Ambos os SGBDs
1. Funções de Janela (Window Functions)
ROW_NUMBER()
Esta função atribui um número sequencial único para cada linha dentro de uma partição dos dados. É extremamente útil para paginação e ranking.
-- Numerar pedidos por cliente em ordem cronológica
SELECT
cliente_id,
id as pedido_id,
data_pedido,
valor_total,
ROW_NUMBER() OVER (PARTITION BY cliente_id ORDER BY data_pedido) as numero_pedido
FROM pedidos;
cliente_id,pedido_id,data_pedido,valor_total,numero_pedido
1,1,"2024-03-01 10:30:00",929.98,1
1,3,"2024-03-03 09:45:00",79.98,2
2,2,"2024-03-02 14:15:00",1349.98,1
3,4,"2024-03-04 16:20:00",249.98,1
Code language: CSS (css)
RANK() e DENSE_RANK()
Essas funções criam rankings, sendo que RANK() pula números quando há empates, enquanto DENSE_RANK() não pula.
-- Ranking de produtos por preço (com empates)
SELECT
nome,
preco,
RANK() OVER (ORDER BY preco DESC) as ranking,
DENSE_RANK() OVER (ORDER BY preco DESC) as ranking_denso
FROM produtos
WHERE ativo = true;
nome,preco,ranking,ranking_denso
Laptop,1299.99,1,1
Smartphone,899.99,2,2
Mesa,199.99,3,3
"Livro SQL",49.99,4,4
Camiseta,29.99,5,5
Code language: CSS (css)
LAG() e LEAD()
Essas funções permitem acessar dados de linhas anteriores (LAG) ou posteriores (LEAD) sem usar self-joins complexos.
-- Comparar valor do pedido atual com o anterior do mesmo cliente
SELECT
cliente_id,
data_pedido,
valor_total,
LAG(valor_total, 1) OVER (PARTITION BY cliente_id ORDER BY data_pedido) as valor_anterior,
valor_total - LAG(valor_total, 1) OVER (PARTITION BY cliente_id ORDER BY data_pedido) as diferenca
FROM pedidos;
cliente_id,data_pedido,valor_total,valor_anterior,diferenca
1,"2024-03-01 10:30:00",929.98,,
1,"2024-03-03 09:45:00",79.98,929.98,-850.0
2,"2024-03-02 14:15:00",1349.98,,
3,"2024-03-04 16:20:00",249.98,,
Code language: CSS (css)
2. Expressões CASE Avançadas
CASE com Agregações
O CASE pode ser usado dentro de funções de agregação para criar relatórios pivotados dinâmicos.
-- Contar pedidos por status em colunas separadas
SELECT
EXTRACT(MONTH FROM data_pedido) as mes,
COUNT(CASE WHEN status = 'entregue' THEN 1 END) as entregues,
COUNT(CASE WHEN status = 'processando' THEN 1 END) as processando,
COUNT(CASE WHEN status = 'cancelado' THEN 1 END) as cancelados,
COUNT(*) as total
FROM pedidos
GROUP BY EXTRACT(MONTH FROM data_pedido);
mes,entregues,processando,cancelados,total
03,2,1,1,4
3. CTEs (Common Table Expressions)
CTE Básico
CTEs criam consultas temporárias nomeadas que tornam o código mais legível e permitem referências múltiplas.
-- CTE para calcular estatísticas de vendas por categoria
WITH vendas_categoria AS (
SELECT
c.nome as categoria,
SUM(ip.quantidade * ip.preco_unitario) as total_vendas,
COUNT(DISTINCT p.id) as total_pedidos
FROM categorias c
JOIN produtos pr ON c.id = pr.categoria_id
JOIN itens_pedido ip ON pr.id = ip.produto_id
JOIN pedidos p ON ip.pedido_id = p.id
WHERE p.status = 'entregue'
GROUP BY c.id, c.nome
)
SELECT
categoria,
total_vendas,
total_pedidos,
total_vendas / total_pedidos as ticket_medio
FROM vendas_categoria
ORDER BY total_vendas DESC;
categoria,total_vendas,total_pedidos,ticket_medio
"Eletrônicos",899.99,1,899.99
Casa,199.99,1,199.99
Livros,49.99,1,49.99
Roupas,29.99,1,29.99Code language: CSS (css)
CTE Recursivo
CTEs recursivos são poderosos para trabalhar com hierarquias ou gerar sequências.
-- Gerar série de datas para análise de vendas diárias
WITH RECURSIVE serie_datas AS (
SELECT DATE '2024-03-01' as data
UNION ALL
SELECT data + INTERVAL '1 day'
FROM serie_datas
WHERE data < DATE '2024-03-31'
)
SELECT
sd.data,
COALESCE(COUNT(p.id), 0) as pedidos_dia,
COALESCE(SUM(p.valor_total), 0) as vendas_dia
FROM serie_datas sd
LEFT JOIN pedidos p ON DATE(p.data_pedido) = sd.data
GROUP BY sd.data
ORDER BY sd.data;
data,pedidos_dia,vendas_dia
2024-03-01,1,929.98
2024-03-02,1,1349.98
2024-03-03,1,79.98
2024-03-04,1,249.98
2024-03-05,0,0Code language: CSS (css)
4. Função COALESCE()
Esta função retorna o primeiro valor não nulo de uma lista de expressões. É extremamente útil para tratar valores nulos.
-- Tratar valores nulos em relatórios
SELECT
nome,
COALESCE(estoque, 0) as estoque_atual,
COALESCE(estoque * preco, 0) as valor_estoque,
CASE
WHEN COALESCE(estoque, 0) = 0 THEN 'Sem estoque'
WHEN COALESCE(estoque, 0) < 10 THEN 'Estoque baixo'
ELSE 'Estoque normal'
END as status_estoque
FROM produtos;
nome,estoque_atual,valor_estoque,status_estoque
Smartphone,50,44999.5,"Estoque normal"
Laptop,30,38999.7,"Estoque normal"
Camiseta,100,2999.0,"Estoque normal"
"Livro SQL",75,3749.25,"Estoque normal"
Mesa,25,4999.75,"Estoque normal"Code language: SQL (Structured Query Language) (sql)
5. Funções de String Avançadas
CONCAT() e CONCAT_WS()
Para concatenar strings de forma segura, tratando valores nulos automaticamente.
-- Criar nomes completos e endereços formatados
SELECT
CONCAT(nome, ' (', email, ')') as cliente_completo,
CONCAT_WS(', ', cidade, estado) as localizacao
FROM clientes;
cliente_completo,localizacao
"João Silva (joao@email.com)","São Paulo, SP"
"Maria Santos (maria@email.com)","Rio de Janeiro, RJ"
"Pedro Costa (pedro@email.com)","Belo Horizonte, MG"Code language: JavaScript (javascript)
SUBSTRING() e POSITION()
Para extrair e localizar partes específicas de strings.
-- Extrair domínio do email e primeira letra do nome
SELECT
nome,
SUBSTRING(nome, 1, 1) as inicial,
SUBSTRING(email, POSITION('@' IN email) + 1) as dominio_email
FROM clientes;
nome,inicial,dominio_email
"João Silva",J,email.com
"Maria Santos",M,email.com
"Pedro Costa",P,email.comCode language: JavaScript (javascript)
Parte 2: Funções Específicas do PostgreSQL
1. Arrays
PostgreSQL oferece suporte nativo robusto para arrays, permitindo armazenar múltiplos valores em uma única coluna.
-- Exemplo com arrays (PostgreSQL)
-- Criar uma tabela com campo array
CREATE TABLE tags_produto (
produto_id INT,
tags TEXT[]
);
-- Inserir dados com arrays
INSERT INTO tags_produto VALUES
(1, ARRAY['tecnologia', 'comunicação', 'móvel']),
(2, ARRAY['tecnologia', 'trabalho', 'portátil']),
(3, ARRAY['moda', 'casual', 'algodão']);
-- Consultar usando operadores de array
SELECT
p.nome,
tp.tags,
array_length(tp.tags, 1) as numero_tags
FROM produtos p
JOIN tags_produto tp ON p.id = tp.produto_id
WHERE 'tecnologia' = ANY(tp.tags);
nome | tags | numero_tags
-------------+---------------------------+-------------
Smartphone | {tecnologia,comunicação,móvel} | 3
Laptop | {tecnologia,trabalho,portátil} | 3
2. Funções JSON/JSONB
PostgreSQL tem excelente suporte para dados JSON, permitindo armazenar e consultar dados semi-estruturados.
-- Exemplo com JSONB (PostgreSQL)
-- Adicionar coluna JSON à tabela produtos
ALTER TABLE produtos ADD COLUMN especificacoes JSONB;
-- Atualizar com dados JSON
UPDATE produtos
SET especificacoes = '{"peso": "150g", "cor": "preto", "garantia": "12 meses"}'::jsonb
WHERE id = 1;
UPDATE produtos
SET especificacoes = '{"peso": "2kg", "tela": "15.6", "memoria": "8GB"}'::jsonb
WHERE id = 2;
-- Consultar dados JSON
SELECT
nome,
especificacoes->>'peso' as peso,
especificacoes->>'cor' as cor,
especificacoes ? 'garantia' as tem_garantia
FROM produtos
WHERE especificacoes IS NOT NULL;
nome | peso | cor | tem_garantia
-------------+------+-------+--------------
Smartphone | 150g | preto | t
Laptop | 2kg | | f
3. Função GENERATE_SERIES()
Gera sequências de valores, muito útil para criar relatórios com períodos completos.
-- Gerar relatório de vendas por dia (PostgreSQL)
SELECT
data_serie::date as data,
COALESCE(COUNT(p.id), 0) as pedidos,
COALESCE(SUM(p.valor_total), 0) as total_vendas
FROM generate_series('2024-03-01'::date, '2024-03-10'::date, '1 day') as data_serie
LEFT JOIN pedidos p ON DATE(p.data_pedido) = data_serie::date
GROUP BY data_serie
ORDER BY data_serie;
data | pedidos | total_vendas
------------+---------+--------------
2024-03-01 | 1 | 929.98
2024-03-02 | 1 | 1349.98
2024-03-03 | 1 | 79.98
2024-03-04 | 1 | 249.98
2024-03-05 | 0 | 0.00
2024-03-06 | 0 | 0.00
2024-03-07 | 0 | 0.00
2024-03-08 | 0 | 0.00
2024-03-09 | 0 | 0.00
2024-03-10 | 0 | 0.00
4. Função STRING_AGG()
Concatena valores de múltiplas linhas em uma única string, com separador personalizado.
-- Listar todos os produtos por categoria (PostgreSQL)
SELECT
c.nome as categoria,
STRING_AGG(p.nome, ', ' ORDER BY p.nome) as produtos,
COUNT(p.id) as total_produtos
FROM categorias c
LEFT JOIN produtos p ON c.id = p.categoria_id
GROUP BY c.id, c.nome;
categoria | produtos | total_produtos
-------------+-----------------------+----------------
Eletrônicos | Laptop, Smartphone | 2
Roupas | Camiseta | 1
Livros | Livro SQL | 1
Casa | Mesa | 1
Parte 3: Funções Específicas do MySQL
1. Função GROUP_CONCAT()
Equivalente ao STRING_AGG do PostgreSQL, mas com sintaxe diferente.
-- Listar produtos por categoria (MySQL)
SELECT
c.nome as categoria,
GROUP_CONCAT(p.nome ORDER BY p.nome SEPARATOR ', ') as produtos,
COUNT(p.id) as total_produtos
FROM categorias c
LEFT JOIN produtos p ON c.id = p.categoria_id
GROUP BY c.id, c.nome;
+-------------+-----------------------+----------------+
| categoria | produtos | total_produtos |
+-------------+-----------------------+----------------+
| Eletrônicos | Laptop, Smartphone | 2 |
| Roupas | Camiseta | 1 |
| Livros | Livro SQL | 1 |
| Casa | Mesa | 1 |
+-------------+-----------------------+----------------+
2. Funções JSON (MySQL 5.7+)
MySQL também oferece suporte para JSON, mas com sintaxe ligeiramente diferente.
-- Trabalhar com JSON no MySQL
-- Adicionar coluna JSON
ALTER TABLE produtos ADD COLUMN detalhes JSON;
-- Inserir dados JSON
UPDATE produtos
SET detalhes = JSON_OBJECT('peso', '150g', 'cor', 'preto', 'garantia', '12 meses')
WHERE id = 1;
-- Consultar dados JSON
SELECT
nome,
JSON_EXTRACT(detalhes, '$.peso') as peso,
JSON_EXTRACT(detalhes, '$.cor') as cor,
JSON_CONTAINS_PATH(detalhes, 'one', '$.garantia') as tem_garantia
FROM produtos
WHERE detalhes IS NOT NULL;
+------------+--------+---------+--------------+
| nome | peso | cor | tem_garantia |
+------------+--------+---------+--------------+
| Smartphone | "150g" | "preto" | 1 |
+------------+--------+---------+--------------+Code language: JavaScript (javascript)
3. Função FIND_IN_SET()
Específica do MySQL para buscar em listas separadas por vírgula.
-- Exemplo com FIND_IN_SET (MySQL)
-- Criar campo com lista de características
ALTER TABLE produtos ADD COLUMN caracteristicas VARCHAR(255);
UPDATE produtos SET caracteristicas = 'resistente,portátil,moderno' WHERE id = 1;
UPDATE produtos SET caracteristicas = 'leve,rápido,silencioso' WHERE id = 2;
-- Buscar produtos com característica específica
SELECT nome, caracteristicas
FROM produtos
WHERE FIND_IN_SET('portátil', caracteristicas) > 0;
+------------+-----------------------------+
| nome | caracteristicas |
+------------+-----------------------------+
| Smartphone | resistente,portátil,moderno |
+------------+-----------------------------+
4. Função IF()
Uma alternativa mais concisa ao CASE para condições simples.
-- Usar IF para classificações simples (MySQL)
SELECT
nome,
preco,
IF(preco > 500, 'Caro', 'Barato') as classificacao_preco,
IF(estoque > 50, 'Alto', IF(estoque > 20, 'Médio', 'Baixo')) as nivel_estoque
FROM produtos;
+------------+---------+--------------------+--------------+
| nome | preco | classificacao_preco| nivel_estoque|
+------------+---------+--------------------+--------------+
| Smartphone | 899.99 | Caro | Médio |
| Laptop | 1299.99 | Caro | Médio |
| Camiseta | 29.99 | Barato | Alto |
| Livro SQL | 49.99 | Barato | Alto |
| Mesa | 199.99 | Barato | Médio |
+------------+---------+--------------------+--------------+
Casos de Uso Práticos
1. Análise de Coorte de Clientes
Vamos criar uma análise de coorte para entender o comportamento de recompra dos clientes.
-- Análise de coorte (funciona em ambos os SGBDs)
WITH primeira_compra AS (
SELECT
cliente_id,
MIN(DATE(data_pedido)) as data_primeira_compra
FROM pedidos
WHERE status = 'entregue'
GROUP BY cliente_id
),
compras_mensais AS (
SELECT
p.cliente_id,
pc.data_primeira_compra,
DATE(p.data_pedido) as data_compra,
EXTRACT(MONTH FROM AGE(DATE(p.data_pedido), pc.data_primeira_compra)) as mes_desde_primeira
FROM pedidos p
JOIN primeira_compra pc ON p.cliente_id = pc.cliente_id
WHERE p.status = 'entregue'
)
SELECT
data_primeira_compra,
COUNT(DISTINCT CASE WHEN mes_desde_primeira = 0 THEN cliente_id END) as mes_0,
COUNT(DISTINCT CASE WHEN mes_desde_primeira = 1 THEN cliente_id END) as mes_1,
COUNT(DISTINCT CASE WHEN mes_desde_primeira = 2 THEN cliente_id END) as mes_2
FROM compras_mensais
GROUP BY data_primeira_compra
ORDER BY data_primeira_compra;
data_primeira_compra | mes_0 | mes_1 | mes_2
----------------------+-------+-------+-------
2024-03-01 | 1 | 0 | 0
2024-03-04 | 1 | 0 | 0
2. Detecção de Outliers
Identificar pedidos com valores anômalos usando funções estatísticas.
-- Detectar outliers em valores de pedidos
WITH estatisticas AS (
SELECT
AVG(valor_total) as media,
STDDEV(valor_total) as desvio_padrao
FROM pedidos
WHERE status = 'entregue'
)
SELECT
p.id,
p.valor_total,
e.media,
ABS(p.valor_total - e.media) / e.desvio_padrao as z_score,
CASE
WHEN ABS(p.valor_total - e.media) / e.desvio_padrao > 2 THEN 'Outlier'
ELSE 'Normal'
END as classificacao
FROM pedidos p
CROSS JOIN estatisticas e
WHERE p.status = 'entregue'
ORDER BY z_score DESC;
id | valor_total | media | z_scor | classificacao
----+-------------+---------------+----------------+---------------
1 | 929.98 | 589.980000000 | 1.000000000000 | Normal
4 | 249.98 | 589.980000000 | 1.000000000000 | Normal
Resumindo tudão:
Pensando em ajudar os pequenos garfanhotos com essas funções, aqui está um cheatsheet do SQL
| Função | Sintaxe | Descrição |
|---|---|---|
ROW_NUMBER() | ROW_NUMBER() OVER (PARTITION BY col ORDER BY col) | Numera linhas sequencialmente |
RANK() | RANK() OVER (ORDER BY col DESC) | Ranking com pulos em empates |
DENSE_RANK() | DENSE_RANK() OVER (ORDER BY col DESC) | Ranking sem pulos em empates |
LAG() | LAG(col, n) OVER (PARTITION BY col ORDER BY col) | Acessa valor de linha anterior |
LEAD() | LEAD(col, n) OVER (PARTITION BY col ORDER BY col) | Acessa valor de linha posterior |
| Tipo | Sintaxe | Uso |
|---|---|---|
| CTE Simples | WITH nome AS (SELECT ...) SELECT * FROM nome | Consultas temporárias nomeadas |
| CTE Recursivo | WITH RECURSIVE nome AS (SELECT ... UNION ALL SELECT ...) | Hierarquias e séries |
| Função | Sintaxe | Descrição |
|---|---|---|
COALESCE() | COALESCE(col1, col2, 'default') | Primeiro valor não nulo |
CASE | CASE WHEN condição THEN valor ELSE outro END | Condições complexas |
CONCAT() | CONCAT(str1, str2, str3) | Concatenação de strings |
CONCAT_WS() | CONCAT_WS(separador, str1, str2) | Concatenação com separador |
SUBSTRING() | SUBSTRING(string, posição, comprimento) | Extrai parte da string |
POSITION() | POSITION(substring IN string) | Localiza posição na string |
Específicas do PostgreSQL
| Categoria | Função | Sintaxe | Descrição |
|---|---|---|---|
| Arrays | ARRAY[] | ARRAY['val1', 'val2'] | Cria array |
ANY() | WHERE 'valor' = ANY(array_col) | Busca em array | |
array_length() | array_length(array_col, 1) | Tamanho do array | |
| JSON | -> | json_col->'key' | Extrai como JSON |
->> | json_col->>'key' | Extrai como texto | |
? | json_col ? 'key' | Verifica se key existe | |
| Séries | generate_series() | generate_series(1, 100, 1) | Gera sequência numérica |
generate_series('2024-01-01', '2024-12-31', '1 day') | Gera sequência de datas | ||
| String | STRING_AGG() | STRING_AGG(col, ', ' ORDER BY col) | Concatena valores agrupados |
Específicas do MySQL
| Categoria | Função | Sintaxe | Descrição |
|---|---|---|---|
| String | GROUP_CONCAT() | GROUP_CONCAT(col ORDER BY col SEPARATOR ', ') | Concatena valores agrupados |
FIND_IN_SET() | FIND_IN_SET('valor', 'lista,separada,virgula') | Busca em lista CSV | |
| Condicional | IF() | IF(condição, valor_true, valor_false) | Condicional simples |
| JSON | JSON_OBJECT() | JSON_OBJECT('key', value, 'key2', value2) | Cria objeto JSON |
JSON_EXTRACT() | JSON_EXTRACT(json_col, '$.key') | Extrai valor do JSON | |
JSON_CONTAINS_PATH() | JSON_CONTAINS_PATH(json_col, 'one', '$.key') | Verifica se path existe |
Dicas de Performance
| Cenário | Dica | Exemplo |
|---|---|---|
| Window Functions | Use PARTITION BY para limitar escopo | OVER (PARTITION BY categoria_id) |
| CTEs | Prefira CTEs a subqueries aninhadas | WITH dados AS (...) SELECT * FROM dados |
| JSON | Crie índices em campos JSON consultados | CREATE INDEX idx_json ON tab ((json_col->>'key')) |
| Arrays (PG) | Use índices GIN para arrays | CREATE INDEX idx_tags ON tab USING GIN (tags) |
| Strings | CONCAT é mais eficiente que || | CONCAT(a, b, c) vs `a |
Compatibilidade
| Função | MySQL | PostgreSQL | Nota |
|---|---|---|---|
| Window Functions | ✅ 8.0+ | ✅ | – |
| CTEs | ✅ 8.0+ | ✅ | – |
| CTEs Recursivos | ✅ 8.0+ | ✅ | – |
| JSON | ✅ 5.7+ | ✅ 9.2+ | Sintaxes diferentes |
| Arrays | ❌ | ✅ | MySQL: use JSON arrays |
STRING_AGG | ❌ | ✅ | MySQL: use GROUP_CONCAT |
GROUP_CONCAT | ✅ | ❌ | PostgreSQL: use STRING_AGG |
Dica Final: Sempre teste essas funções com seus dados reais e monitore a performance. Algumas funções podem necessitar de índices específicos para otimização adequada.


Deixe um comentário