{"id":27169508,"url":"https://github.com/tsffarias/dbtcore-northwind-postgresql","last_synced_at":"2025-04-09T06:41:19.918Z","repository":{"id":245583030,"uuid":"818680552","full_name":"tsffarias/dbtcore-northwind-postgresql","owner":"tsffarias","description":"Relatórios Avançados em SQL Northwind","archived":false,"fork":false,"pushed_at":"2025-04-08T00:35:08.000Z","size":377,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-08T01:26:31.717Z","etag":null,"topics":["dbt","postgresql","sql"],"latest_commit_sha":null,"homepage":"https://www.linkedin.com/in/thiagosilvafarias/","language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tsffarias.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-22T14:41:18.000Z","updated_at":"2025-04-08T00:35:12.000Z","dependencies_parsed_at":"2025-04-08T05:30:44.771Z","dependency_job_id":null,"html_url":"https://github.com/tsffarias/dbtcore-northwind-postgresql","commit_stats":null,"previous_names":["tsffarias/northwind-advanced-sql-reports","tsffarias/dbtcore-northwind-postgresql"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsffarias%2Fdbtcore-northwind-postgresql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsffarias%2Fdbtcore-northwind-postgresql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsffarias%2Fdbtcore-northwind-postgresql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsffarias%2Fdbtcore-northwind-postgresql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tsffarias","download_url":"https://codeload.github.com/tsffarias/dbtcore-northwind-postgresql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994068,"owners_count":21030048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dbt","postgresql","sql"],"created_at":"2025-04-09T06:41:19.480Z","updated_at":"2025-04-09T06:41:19.896Z","avatar_url":"https://github.com/tsffarias.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Relatórios Avançados em SQL Northwind\n\n## Objetivo\n\nEste repositório tem como objetivo apresentar relatórios avançados construídos em SQL. As análises disponibilizadas aqui podem ser aplicadas em empresas de todos os tamanhos que desejam se tornar mais analíticas. Através destes relatórios, organizações poderão extrair insights valiosos de seus dados, ajudando na tomada de decisões estratégicas.\n\n## Relatórios que vamos criar\n\n1. **Relatórios de Receita**\n    \n    * Qual foi o total de receitas no ano de 1997?\n\n    ```sql\n    CREATE VIEW total_revenues_1997_view AS\n    SELECT SUM((order_details.unit_price) * order_details.quantity * (1.0 - order_details.discount)) AS total_revenues_1997\n    FROM order_details\n    INNER JOIN (\n        SELECT order_id \n        FROM orders \n        WHERE EXTRACT(YEAR FROM order_date) = '1997'\n    ) AS ord \n    ON ord.order_id = order_details.order_id;\n    ```\n\n    * Faça uma análise de crescimento mensal e o cálculo de YTD\n\n    ```sql\n    CREATE VIEW view_receitas_acumuladas AS\n    WITH ReceitasMensais AS (\n        SELECT\n            EXTRACT(YEAR FROM orders.order_date) AS Ano,\n            EXTRACT(MONTH FROM orders.order_date) AS Mes,\n            SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) AS Receita_Mensal\n        FROM\n            orders\n        INNER JOIN\n            order_details ON orders.order_id = order_details.order_id\n        GROUP BY\n            EXTRACT(YEAR FROM orders.order_date),\n            EXTRACT(MONTH FROM orders.order_date)\n    ),\n    ReceitasAcumuladas AS (\n        SELECT\n            Ano,\n            Mes,\n            Receita_Mensal,\n            SUM(Receita_Mensal) OVER (PARTITION BY Ano ORDER BY Mes) AS Receita_YTD\n        FROM\n            ReceitasMensais\n    )\n    SELECT\n        Ano,\n        Mes,\n        Receita_Mensal,\n        Receita_Mensal - LAG(Receita_Mensal) OVER (PARTITION BY Ano ORDER BY Mes) AS Diferenca_Mensal,\n        Receita_YTD,\n        (Receita_Mensal - LAG(Receita_Mensal) OVER (PARTITION BY Ano ORDER BY Mes)) / LAG(Receita_Mensal) OVER (PARTITION BY Ano ORDER BY Mes) * 100 AS Percentual_Mudanca_Mensal\n    FROM\n        ReceitasAcumuladas\n    ORDER BY\n        Ano, Mes;\n    ```\n\n2. **Segmentação de clientes**\n    \n    * Qual é o valor total que cada cliente já pagou até agora?\n\n    ```sql\n    CREATE VIEW view_total_revenues_per_customer AS\n    SELECT \n        customers.company_name, \n        SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) AS total\n    FROM \n        customers\n    INNER JOIN \n        orders ON customers.customer_id = orders.customer_id\n    INNER JOIN \n        order_details ON order_details.order_id = orders.order_id\n    GROUP BY \n        customers.company_name\n    ORDER BY \n        total DESC;\n    ```\n\n    * Separe os clientes em 5 grupos de acordo com o valor pago por cliente\n\n    ```sql\n    CREATE VIEW view_total_revenues_per_customer_group AS\n    SELECT \n    customers.company_name, \n    SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) AS total,\n    NTILE(5) OVER (ORDER BY SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) DESC) AS group_number\n    FROM \n        customers\n    INNER JOIN \n        orders ON customers.customer_id = orders.customer_id\n    INNER JOIN \n        order_details ON order_details.order_id = orders.order_id\n    GROUP BY \n        customers.company_name\n    ORDER BY \n        total DESC;\n    ```\n\n\n    * Agora somente os clientes que estão nos grupos 3, 4 e 5 para que seja feita uma análise de Marketing especial com eles\n\n    ```sql\n    CREATE VIEW clients_to_marketing AS\n    WITH clientes_para_marketing AS (\n        SELECT \n        customers.company_name, \n        SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) AS total,\n        NTILE(5) OVER (ORDER BY SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) DESC) AS group_number\n    FROM \n        customers\n    INNER JOIN \n        orders ON customers.customer_id = orders.customer_id\n    INNER JOIN \n        order_details ON order_details.order_id = orders.order_id\n    GROUP BY \n        customers.company_name\n    ORDER BY \n        total DESC\n    )\n\n    SELECT *\n    FROM clientes_para_marketing\n    WHERE group_number \u003e= 3;\n    ```\n\n3. **Top 10 Produtos Mais Vendidos**\n    \n    * Identificar os 10 produtos mais vendidos.\n\n    ```sql\n    CREATE VIEW top_10_products AS\n    SELECT products.product_name, SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) AS sales\n    FROM products\n    INNER JOIN order_details ON order_details.product_id = products.product_id\n    GROUP BY products.product_name\n    ORDER BY sales DESC;\n    ```\n\n4. **Clientes do Reino Unido que Pagaram Mais de 1000 Dólares**\n    \n    * Quais clientes do Reino Unido pagaram mais de 1000 dólares?\n\n    ```sql\n    CREATE VIEW uk_clients_who_pay_more_then_1000 AS\n    SELECT customers.contact_name, SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount) * 100) / 100 AS payments\n    FROM customers\n    INNER JOIN orders ON orders.customer_id = customers.customer_id\n    INNER JOIN order_details ON order_details.order_id = orders.order_id\n    WHERE LOWER(customers.country) = 'uk'\n    GROUP BY customers.contact_name\n    HAVING SUM(order_details.unit_price * order_details.quantity * (1.0 - order_details.discount)) \u003e 1000;\n    ```\n\n## Contexto\n\nO banco de dados `Northwind` contém os dados de vendas de uma empresa  chamada `Northwind Traders`, que importa e exporta alimentos especiais de todo o mundo. \n\nO banco de dados Northwind é ERP com dados de clientes, pedidos, inventário, compras, fornecedores, remessas, funcionários e contabilidade.\n\nO conjunto de dados Northwind inclui dados de amostra para o seguinte:\n\n* **Fornecedores:** Fornecedores e vendedores da Northwind\n* **Clientes:** Clientes que compram produtos da Northwind\n* **Funcionários:** Detalhes dos funcionários da Northwind Traders\n* **Produtos:** Informações do produto\n* **Transportadoras:** Os detalhes dos transportadores que enviam os produtos dos comerciantes para os clientes finais\n* **Pedidos e Detalhes do Pedido:** Transações de pedidos de vendas ocorrendo entre os clientes e a empresa\n\nO banco de dados `Northwind` inclui 14 tabelas e os relacionamentos entre as tabelas são mostrados no seguinte diagrama de relacionamento de entidades.\n\n![northwind](https://github.com/lvgalvao/Northwind-SQL-Analytics/blob/main/pics/northwind-er-diagram.png?raw=true)\n\n# Utilização de Materialized Views, Triggers e Stored Procedures\n\n**Objetivo: Exemplificar o Uso de Materialized Views, Triggers e Stored Procedures em um Contexto de Business Intelligence**\n\nEste repositório também tem como objetivo apresentar relatórios avançados construídos em SQL, demonstrando a aplicação prática de conceitos fundamentais de Business Intelligence (BI). As análises disponibilizadas aqui são projetadas para serem aplicadas em empresas de todos os tamanhos, ajudando-as a se tornarem mais analíticas e orientadas por dados.\n\n**Como Funciona:**\n\n1. **Materialized Views:** As Materialized Views são utilizadas para pré-calcular e armazenar resultados de consultas complexas. Neste cenário, as Materialized Views são empregadas para melhorar o desempenho de consultas frequentes e fornecer acesso rápido a dados agregados essenciais para análises.\n    \n2. **Triggers:** Triggers são mecanismos que permitem a execução automática de ações em resposta a eventos específicos no banco de dados. Neste contexto, as Triggers são empregadas para garantir a integridade dos dados e aplicar lógica de negócios, como validações e atualizações automáticas.\n    \n3. **Stored Procedures:** Stored Procedures são conjuntos de instruções SQL pré-compiladas e armazenadas no banco de dados. Elas podem ser chamadas repetidamente para executar tarefas complexas de forma eficiente e consistente. Neste caso, as Stored Procedures são utilizadas para automatizar processos de ETL (Extração, Transformação e Carregamento) e realizar operações avançadas de manipulação de dados.\n\n**Benefícios:**\n\n* **Extração de Insights Valiosos:** Os relatórios avançados disponibilizados neste repositório permitem que as organizações extraiam insights valiosos de seus dados, proporcionando uma compreensão mais profunda de seus processos e desempenho.\n* **Apoio à Tomada de Decisões Estratégicas:** Com acesso a análises detalhadas e atualizadas, as empresas podem tomar decisões estratégicas mais informadas e direcionadas, impulsionando o crescimento e a eficiência operacional.]\n\n**Caso Materialized View:**\n\n```mermaid\ngraph TD;\n    B[Trigger trg_refresh_sales_accumulated_monthly_mv_order_details] -- Atualização --\u003e E[Visualização Materializada sales_accumulated_monthly_mv];\n    D[Trigger trg_refresh_sales_accumulated_monthly_mv_orders] -- Atualização --\u003e E;\n    A -- Inserção, Atualização ou Exclusão --\u003e B;\n    C -- Inserção, Atualização ou Exclusão --\u003e D;\n```\n\nEste conjunto de comandos SQL define uma ETL (Extração, Transformação e Carregamento) para gerar um relatório de vendas acumuladas mensais. A ETL consiste em uma visualização materializada chamada `sales_accumulated_monthly_mv` e duas triggers que garantem que a visualização seja atualizada sempre que houver alterações nas tabelas `order_details` e `orders`.\n\n1. **Visualização Materializada (`sales_accumulated_monthly_mv`):** Esta visualização materializada calcula a soma acumulada das vendas mensais. Ela extrai o ano e o mês da data do pedido e calcula a soma das vendas para cada mês. Os resultados são agrupados por ano e mês.\n    \n2. **Trigger para Atualização da Visualização (`trg_refresh_sales_accumulated_monthly_mv_order_details` e `trg_refresh_sales_accumulated_monthly_mv_orders`):** Duas triggers foram criadas para garantir que a visualização materializada seja atualizada sempre que houver alterações nas tabelas `order_details` e `orders`. Quando ocorrerem inserções, atualizações ou exclusões nessas tabelas, as triggers acionarão a função `refresh_sales_accumulated_monthly_mv`, que atualizará a visualização materializada.\n\n**Caso Stored Procedured:**\n\n```mermaid\ngraph TB;\n    D[Procedimento atualizar_titulo_employee] -- Chamada --\u003e A[Tabela employees];\n    A -- Atualização de título --\u003e B[Trigger trg_auditoria_titulo];\n    B -- Registro em employees_auditoria --\u003e C[Tabela employees_auditoria];\n```\n\n\nEste conjunto de comandos SQL visa monitorar e atualizar alterações nos títulos dos funcionários na tabela `employees` e registrar essas mudanças na tabela `employees_auditoria`.\n\n1. **Tabela de Auditoria de Funcionários (`employees_auditoria`):** Uma tabela foi criada para registrar as mudanças nos títulos dos funcionários. Ela possui os seguintes campos:\n    \n    * `employee_id`: O ID do funcionário afetado.\n    * `nome_anterior`: O título anterior do funcionário.\n    * `nome_novo`: O novo título do funcionário.\n    * `data_modificacao`: A data e hora da modificação (com o valor padrão definido como o momento atual).\n2. **Trigger para Auditoria de Títulos (`trg_auditoria_titulo`):** Uma trigger foi criada para ser acionada após a atualização do título na tabela `employees`. Esta trigger chama uma função que registra a mudança na tabela `employees_auditoria`.\n    \n3. **Procedimento para Atualização de Título (`atualizar_titulo_employee`):** Uma stored procedure foi criada para facilitar a atualização do título de um funcionário. Ela aceita o ID do funcionário e o novo título como parâmetros e executa uma atualização na tabela `employees`.\n\n**Conclusão:**\n\nEste repositório oferece uma oportunidade única para empresas de todos os setores aproveitarem o poder do Business Intelligence por meio de relatórios avançados em SQL. Ao adotar essas práticas, as organizações podem transformar dados em insights acionáveis, impulsionando o sucesso e a inovação em um ambiente competitivo.\n\n## Configuração Inicial\n\n### Manualmente\n\nUtilize o arquivo SQL fornecido, `nortwhind.sql`, para popular o seu banco de dados.\n\n### Com Docker e Docker Compose\n\n**Pré-requisito**: Instale o Docker e Docker Compose\n\n* [Começar com Docker](https://www.docker.com/get-started)\n* [Instalar Docker Compose](https://docs.docker.com/compose/install/)\n\n### Passos para configuração com Docker:\n\n1. **Iniciar o Docker Compose** Execute o comando abaixo para subir os serviços:\n    \n    ```\n    docker-compose up -d --build\n    ```\n    \n    Aguarde as mensagens de configuração, como:\n    \n    ```csharp\n    Creating network \"northwind_psql_db\" with driver \"bridge\"\n    Creating volume \"northwind_psql_db\" with default driver\n    Creating volume \"northwind_psql_pgadmin\" with default driver\n    Creating pgadmin ... done\n    Creating db      ... done\n    ```\n       \n2. **Conectar o PgAdmin** Acesse o PgAdmin pelo URL: [http://localhost:5050](http://localhost:5050), com a senha `postgres`. \n\nConfigure um novo servidor no PgAdmin:\n    \n    * **Aba General**:\n        * Nome: db\n    * **Aba Connection**:\n        * Nome do host: db\n        * Nome de usuário: postgres\n        * Senha: postgres Em seguida, selecione o banco de dados \"northwind\".\n\n3. **Parar o Docker Compose** Pare o servidor iniciado pelo comando `docker-compose up` usando Ctrl-C e remova os contêineres com:\n    \n    ```\n    docker-compose down\n    ```\n    \n4. **Arquivos e Persistência** Suas modificações nos bancos de dados Postgres serão persistidas no volume Docker `postgresql_data` e podem ser recuperadas reiniciando o Docker Compose com `docker-compose up`. Para deletar os dados do banco, execute:\n    \n    ```\n    docker-compose down -v\n    ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsffarias%2Fdbtcore-northwind-postgresql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftsffarias%2Fdbtcore-northwind-postgresql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsffarias%2Fdbtcore-northwind-postgresql/lists"}