commit 8c688729db186c9bd0c0c43e00fb0ad72dd5083e Author: IdalecioSch Date: Wed Jun 24 18:46:44 2026 -0300 sss diff --git a/1_modeloBase.sql b/1_modeloBase.sql new file mode 100644 index 0000000..3a25201 --- /dev/null +++ b/1_modeloBase.sql @@ -0,0 +1,68 @@ + +CREATE TYPE tipo_contato AS ENUM ('email', 'telefone', 'celular', 'whatsapp'); + +CREATE TABLE cliente ( + id SERIAL PRIMARY KEY, + cpf CHAR(11) NOT NULL, + nome VARCHAR(50) NOT NULL +); + +CREATE TABLE cor ( + id SERIAL PRIMARY KEY, + descricao VARCHAR(20) NOT NULL, + fundo BOOLEAN NOT NULL, + frase BOOLEAN NOT NULL +); + +CREATE TABLE material ( + id SERIAL PRIMARY KEY, + descricao VARCHAR(20) NOT NULL, + valor_letra DECIMAL(10,2) NOT NULL, + custo DECIMAL(10,2) NOT NULL +); + +CREATE TABLE desconto ( + id SERIAL PRIMARY KEY, + valor_minimo DECIMAL(10,2) NOT NULL, + valor_maximo DECIMAL(10,2) NOT NULL, + percentual DECIMAL(5,2) NOT NULL +); + +CREATE TABLE contato ( + id SERIAL PRIMARY KEY, + cliente_id INTEGER NOT NULL, + tipo tipo_contato NOT NULL, + informacao VARCHAR(50) NOT NULL, + CONSTRAINT fk_contato_cliente FOREIGN KEY (cliente_id) REFERENCES cliente(id) +); + +CREATE TABLE placa ( + id SERIAL PRIMARY KEY, + largura INTEGER NOT NULL, + altura INTEGER NOT NULL, + material_id INTEGER NOT NULL, + CONSTRAINT fk_placa_material FOREIGN KEY (material_id) REFERENCES material(id) +); + +CREATE TABLE encomenda ( + id SERIAL PRIMARY KEY, + data TIMESTAMP NOT NULL, + entrega TIMESTAMP NOT NULL, + cliente_id INTEGER NOT NULL, + desconto_id INTEGER NOT NULL, + CONSTRAINT fk_encomenda_cliente FOREIGN KEY (cliente_id) REFERENCES cliente(id), + CONSTRAINT fk_encomenda_desconto FOREIGN KEY (desconto_id) REFERENCES desconto(id) +); + +CREATE TABLE item ( + id SERIAL PRIMARY KEY, + encomenda_id INTEGER NOT NULL, + placa_id INTEGER NOT NULL, + frase VARCHAR(50) NOT NULL, + cor_fundo_id INTEGER NOT NULL, + cor_frase_id INTEGER NOT NULL, + CONSTRAINT fk_item_encomenda FOREIGN KEY (encomenda_id) REFERENCES encomenda(id), + CONSTRAINT fk_item_placa FOREIGN KEY (placa_id) REFERENCES placa(id), + CONSTRAINT fk_item_cor_fundo FOREIGN KEY (cor_fundo_id) REFERENCES cor(id), + CONSTRAINT fk_item_cor_frase FOREIGN KEY (cor_frase_id) REFERENCES cor(id) +); diff --git a/2_alteracoes.sql b/2_alteracoes.sql new file mode 100644 index 0000000..62a10df --- /dev/null +++ b/2_alteracoes.sql @@ -0,0 +1,31 @@ + +ALTER TABLE encomenda + ADD COLUMN valor DECIMAL(10,2) NOT NULL DEFAULT 0.00; + + +CREATE TABLE recebimento ( + id SERIAL PRIMARY KEY, + encomenda_id INTEGER NOT NULL, + sinal DECIMAL(10,2) NOT NULL, + data_sinal TIMESTAMP NOT NULL, + restante DECIMAL(10,2) NOT NULL, + data_restante TIMESTAMP NOT NULL, + CONSTRAINT fk_recebimento_encomenda + FOREIGN KEY (encomenda_id) REFERENCES encomenda(id) +); + + +ALTER TABLE encomenda + DROP CONSTRAINT fk_encomenda_desconto; + +ALTER TABLE encomenda + DROP COLUMN desconto_id; + +DROP TABLE desconto; + + + +ALTER TABLE encomenda + ADD COLUMN situacao VARCHAR(10) NOT NULL DEFAULT 'Aberta' + CONSTRAINT chk_encomenda_situacao CHECK (situacao IN ('Aberta', 'Fechada')); + diff --git a/3_triggers.md b/3_triggers.md new file mode 100644 index 0000000..9d39c6d --- /dev/null +++ b/3_triggers.md @@ -0,0 +1,104 @@ +### 3 — Trigger antes de insercao pra poder ja ser chamada ao inserir dados + +Fun trigger 1 atualiza encomenda.valor quando insere/altera/exclui + +Calcula o valor da encomenda quando adiciona um novo item no pedido, formula: `material.custo + LENGTH(item.frase) × material.valor_letra`. + + +```sql +CREATE FUNCTION fun_att_valor_enc() +RETURNS TRIGGER AS $$ +DECLARE + val_enc_id INTEGER; +BEGIN + IF TG_OP = 'DELETE' THEN + val_enc_id := OLD.encomenda_id; -- old pq pega o item.encomenda id antes de apagar + ELSE + val_enc_id := NEW.encomenda_id; -- new pq pega o item.encomenda_id depois de alterar/inserir + END IF; + + + UPDATE encomenda + SET valor = ( + SELECT COALESCE( + SUM(m.custo + LENGTH(i.frase) * m.valor_letra), + 0.00 + ) + -- Coalese pq ele tenta pegar sum, se ficar null, retorna 0.00 msm, como um operador ternario + FROM item i + JOIN placa p ON p.id = i.placa_id + JOIN material m ON m.id = p.material_id + WHERE i.encomenda_id = val_enc_id + ) + WHERE id = val_enc_id; + + + IF TG_OP = 'UPDATE' AND OLD.encomenda_id <> NEW.encomenda_id THEN + UPDATE encomenda + SET valor = ( + SELECT COALESCE( + SUM(m.custo + LENGTH(i.frase) * m.valor_letra), + 0.00 + ) + FROM item i + JOIN placa p ON p.id = i.placa_id + JOIN material m ON m.id = p.material_id + WHERE i.encomenda_id = OLD.encomenda_id + ) + WHERE id = OLD.encomenda_id; + END IF; + + IF TG_OP = 'DELETE' THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; +END; +$$ LANGUAGE plpgsql; +``` + +fun trigger 2 — registra recebimento quando fecha encomenda + +Quando encomenda.situacao() passa de aberta pra Fechada, bota uma linha em +recebimento com: + +- snal = 1/2 do valor total -> vence na data encomenda.data +- resto = restante -> vence na data de encomenda.entrega + + +```sql +CREATE OR REPLACE FUNCTION fun_fechar_encomenda() +RETURNS TRIGGER AS $$ +BEGIN + -- so quando muda de Aberta pra Fechada + IF NEW.situacao = 'Fechada' AND OLD.situacao = 'Aberta' THEN + INSERT INTO recebimento (encomenda_id, sinal, data_sinal, restante, data_restante) + VALUES ( + NEW.id, + (NEW.valor * 0.50), + NEW.data, + (NEW.valor * 0.50), + NEW.entrega + ); + END IF; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +``` +--- +triggers + +```sql +CREATE TRIGGER trg_fechar_encomenda + AFTER UPDATE ON encomenda + FOR EACH ROW + EXECUTE FUNCTION fun_fechar_encomenda(); + + +CREATE TRIGGER trg_att_valor_enc + AFTER INSERT OR UPDATE OR DELETE ON item + FOR EACH ROW + EXECUTE FUNCTION fun_att_valor_enc(); + +``` diff --git a/4_insercoes.sql b/4_insercoes.sql new file mode 100644 index 0000000..26321b1 --- /dev/null +++ b/4_insercoes.sql @@ -0,0 +1,132 @@ + + + +INSERT INTO cliente (cpf, nome) VALUES + ('11122233344', 'Marco Aurelio'), + ('22233344455', 'Fernando Bastos'), + ('33344455566', 'Fabiano Gabardo'), + ('44455566677', 'Jullian Hermann'), + ('55566677788', 'Cleber Nardelli'); + + + + + +INSERT INTO material (descricao, valor_letra, custo) VALUES + ('Aluminio', 2.50, 15.00), + ('Plutonio', 1.50, 8.00), + ('Acrilico', 3.00, 20.00); + + + +INSERT INTO placa (largura, altura, material_id) VALUES + (20, 10, 1), -- Aluminio + (30, 15, 2), -- Plutonio + (40, 20, 3), -- Acrilico + (25, 12, 1), -- Aluminio + (35, 18, 2); -- Plutonio + + + + +INSERT INTO cor (descricao, fundo, frase) VALUES + ('Branco', TRUE, FALSE), + ('Preto', FALSE, TRUE), + ('Vermelho', TRUE, TRUE), + ('Azul', TRUE, TRUE), + ('Amarelo', TRUE, FALSE), + ('Verde', TRUE, TRUE), + ('Laranja', TRUE, FALSE), + ('Cinza', FALSE, TRUE); + + + + + +INSERT INTO encomenda (data, entrega, cliente_id, valor, situacao) VALUES +-- Marco Aurelio +('2026-01-10 09:00', '2026-01-20 18:00', 1, 0.00, 'Aberta'), +('2026-02-05 10:00', '2026-02-15 18:00', 1, 0.00, 'Aberta'), +('2026-03-12 11:00', '2026-03-22 18:00', 1, 0.00, 'Aberta'), +('2026-04-18 14:00', '2026-04-28 18:00', 1, 0.00, 'Aberta'), +-- Fernando Bastos +('2026-01-15 09:30', '2026-01-25 18:00', 2, 0.00, 'Aberta'), +('2026-02-20 10:30', '2026-03-02 18:00', 2, 0.00, 'Aberta'), +('2026-03-25 11:30', '2026-04-04 18:00', 2, 0.00, 'Aberta'), +('2026-04-30 14:30', '2026-05-10 18:00', 2, 0.00, 'Aberta'), +-- Fabiano Gabardo +('2026-01-20 08:00', '2026-01-30 18:00', 3, 0.00, 'Aberta'), +('2026-02-25 09:00', '2026-03-07 18:00', 3, 0.00, 'Aberta'), +('2026-03-30 10:00', '2026-04-09 18:00', 3, 0.00, 'Aberta'), +('2026-05-05 15:00', '2026-05-15 18:00', 3, 0.00, 'Aberta'), +-- Jullian Hermann +('2026-01-25 09:00', '2026-02-04 18:00', 4, 0.00, 'Aberta'), +('2026-02-28 10:00', '2026-03-10 18:00', 4, 0.00, 'Aberta'), +('2026-04-02 11:00', '2026-04-12 18:00', 4, 0.00, 'Aberta'), +('2026-05-08 14:00', '2026-05-18 18:00', 4, 0.00, 'Aberta'), +-- Cleber Nardelli +('2026-02-01 08:30', '2026-02-11 18:00', 5, 0.00, 'Aberta'), +('2026-03-07 09:30', '2026-03-17 18:00', 5, 0.00, 'Aberta'), +('2026-04-10 10:30', '2026-04-20 18:00', 5, 0.00, 'Aberta'), +('2026-05-15 15:30', '2026-05-25 18:00', 5, 0.00, 'Aberta'); + + + + +INSERT INTO item (encomenda_id, placa_id, frase, cor_fundo_id, cor_frase_id) VALUES + +(1, 1, 'Proibido Entrar', 1, 2), +(1, 2, 'Saída Emergência', 3, 8), +(2, 3, 'Cuidado Elétrico', 4, 2), +(2, 4, 'Área Restrita', 5, 3), +(3, 5, 'Bem-vindo', 6, 2), +(3, 1, 'Atenção Obra', 1, 4), +(4, 2, 'Proibido Fumar', 3, 2), +(4, 3, 'Silêncio Hospital', 4, 8), +(5, 4, 'Loja Aberta', 7, 2), +(5, 5, 'Use EPI', 1, 6), +(6, 1, 'Recepção', 5, 4), +(6, 2, 'Banheiro Fem.', 6, 2), +(7, 3, 'Banheiro Masc.', 3, 8), +(7, 4, 'Piso Escorregadio', 5, 2), +(8, 5, 'Estacionamento', 1, 3), +(8, 1, 'Proibido Parar', 3, 2), +(9, 2, 'Entrada Proibida', 4, 2), +(9, 3, 'Piso Molhado', 7, 4), +(10, 4, 'Cuidado com o Cão', 1, 6), +(10, 5, 'Velocidade 30 km', 5, 2), +(11, 1, 'Portaria', 6, 2), +(11, 2, 'Segurança 24h', 1, 4), +(11, 3, 'Guarita', 3, 8), +(12, 4, 'Direção Proibida', 4, 2), +(12, 5, 'Pare', 3, 8), +(12, 1, 'Dê a Preferência', 5, 2), +(13, 2, 'Depósito', 1, 3), +(13, 3, 'Almoxarifado', 6, 2), +(13, 4, 'Produção', 4, 8), +(14, 5, 'Escritório', 1, 4), +(14, 1, 'Sala de Reunião', 3, 2), +(14, 2, 'TI', 5, 6), +(15, 3, 'Financeiro', 6, 2), +(15, 4, 'RH', 1, 4), +(15, 5, 'Diretoria', 4, 8), +(16, 1, 'Marketing', 3, 2), +(16, 2, 'Comercial', 7, 4), +(16, 3, 'Logística', 1, 6), +(17, 4, 'Manutenção', 5, 2), +(17, 5, 'Qualidade', 6, 8), +(17, 1, 'Expedição', 3, 4), +(18, 2, 'Controle de Acesso', 1, 2), +(18, 3, 'Câmeras Ativas', 4, 8), +(18, 4, 'Monitorado 24 horas', 3, 2), +(19, 5, 'Saída', 6, 2), +(19, 1, 'Entrada', 1, 4), +(19, 2, 'Carga e Descarga', 5, 3), +(20, 3, 'Refeitório', 7, 2), +(20, 4, 'Vestiário', 6, 8), +(20, 5, 'Emergência', 3, 2); + + +UPDATE encomenda SET situacao = 'Fechada' +WHERE id IN (1, 2, 5, 6, 9, 13, 17); + diff --git a/5_consultas.md b/5_consultas.md new file mode 100644 index 0000000..c13a0dd --- /dev/null +++ b/5_consultas.md @@ -0,0 +1,120 @@ + +Consulta 1 — `SELECT … FROM … JOIN` + +> Listar todos os itens com dados da placa, material e nome do cliente. + +```sql +SELECT + e.id AS encomenda_id, + c.nome AS cliente, + i.frase, + p.largura || 'x' || p.altura AS dimensao_cm, + m.descricao AS material +FROM item i +JOIN encomenda e ON e.id = i.encomenda_id +JOIN cliente c ON c.id = e.cliente_id +JOIN placa p ON p.id = i.placa_id +JOIN material m ON m.id = p.material_id; +``` + +--- + +Consulta 2 — `SELECT … FROM … JOIN … WHERE` + +> Encomendas abertas de um cliente específico, com valor acima de zero. + +```sql +SELECT + e.id, + e.data, + e.entrega, + e.valor, + c.nome AS cliente +FROM encomenda e +JOIN cliente c ON c.id = e.cliente_id +WHERE c.nome = 'Ana Silva' + AND e.situacao = 'Aberta' + AND e.valor > 0 +ORDER BY e.data; +``` + +--- + +Consulta 3 — `SELECT … FROM … JOIN … GROUP BY` + +> Quantidade de itens e valor total por encomenda. + +```sql +SELECT + e.id AS encomenda_id, + c.nome AS cliente, + e.situacao, + COUNT(i.id) AS total_itens, + e.valor AS valor_encomenda +FROM encomenda e +JOIN cliente c ON c.id = e.cliente_id +JOIN item i ON i.encomenda_id = e.id +GROUP BY e.id, c.nome, e.situacao, e.valor +ORDER BY total_itens DESC; +``` + +--- + +Consulta 4 — `SELECT … FROM … JOIN … WHERE … GROUP BY` + +> Total de encomendas e receita por cliente, apenas para encomendas fechadas. + +```sql +SELECT + c.nome AS cliente, + COUNT(e.id) AS total_encomendas, + SUM(e.valor) AS receita_total +FROM encomenda e +JOIN cliente c ON c.id = e.cliente_id +WHERE e.situacao = 'Fechada' +GROUP BY c.id, c.nome +ORDER BY receita_total DESC; +``` + +--- + +Consulta 5 — `SELECT … FROM … JOIN … GROUP BY … HAVING` + +> Encomendas com mais de 2 itens (independente de status). + +```sql +SELECT + e.id AS encomenda_id, + c.nome AS cliente, + e.situacao, + COUNT(i.id) AS total_itens +FROM encomenda e +JOIN cliente c ON c.id = e.cliente_id +JOIN item i ON i.encomenda_id = e.id +GROUP BY e.id, c.nome, e.situacao +HAVING COUNT(i.id) > 2 +ORDER BY total_itens DESC; +``` + +--- + +Consulta 6 — `SELECT … FROM … JOIN … WHERE … GROUP BY … HAVING` + +> Materiais usados em encomendas abertas a partir de março de 2024, +> com valor médio por item acima de R$ 30,00. + +```sql +SELECT + m.descricao AS material, + COUNT(i.id) AS total_itens, + ROUND(AVG(m.custo + LENGTH(i.frase) * m.valor_letra), 2) AS valor_medio_item +FROM item i +JOIN encomenda e ON e.id = i.encomenda_id +JOIN placa p ON p.id = i.placa_id +JOIN material m ON m.id = p.material_id +WHERE e.situacao = 'Aberta' + AND e.data >= '2024-03-01' +GROUP BY m.id, m.descricao +HAVING AVG(m.custo + LENGTH(i.frase) * m.valor_letra) > 30 +ORDER BY valor_medio_item DESC; +``` diff --git a/6_views.md b/6_views.md new file mode 100644 index 0000000..6540e82 --- /dev/null +++ b/6_views.md @@ -0,0 +1,57 @@ +# 5.5 — Views + +--- + +View 1 — 3 clientes com maior receita + +Considera apenas encomendas com `situacao = 'Fechada'` + +```sql +CREATE OR REPLACE VIEW viww_top3_clientes_receita AS +SELECT + c.id, + c.nome, + c.cpf, + COUNT(e.id) AS total_encomendas, + SUM(e.valor) AS receita_total +FROM cliente c +JOIN encomenda e ON e.cliente_id = c.id +WHERE e.situacao = 'Fechada' +GROUP BY c.id, c.nome, c.cpf +ORDER BY receita_total DESC +LIMIT 3; +``` + +```sql +SELECT * FROM viww_top3_clientes_receita; +``` + +--- + +View 2 — Valor arrecadado por placa + +Soma o valor gerado por cada tipo de placa nas encomendas fechadas. +O valor por item é calculado como `material.custo + LENGTH(frase) × material.valor_letra`. + +```sql +CREATE VIEW view_valor_por_placa AS +SELECT + p.id AS placa_id, + p.largura || ' x ' || p.altura || ' cm' AS dimensao, + m.descricao AS material, + COUNT(i.id) AS total_vendas, + ROUND( + SUM(m.custo + LENGTH(i.frase) * m.valor_letra), 2 + ) AS valor_arrecadado +FROM placa p +JOIN item i ON i.placa_id = p.id +JOIN encomenda e ON e.id = i.encomenda_id +JOIN material m ON m.id = p.material_id +WHERE e.situacao = 'Fechada' +GROUP BY p.id, p.largura, p.altura, m.descricao +ORDER BY valor_arrecadado DESC; +``` + +```sql +SELECT * FROM view_valor_por_placa; +```