SlideShare a Scribd company logo
Funções Analíticas com SQL
1
● 13 anos com desenvolvimento de software
● 2 certificações Java
● Formação DBA Oracle
● Responsável pelo BI da Beleza na Web
● Entusiasta pelo mercado financeiro e economia
● Formação em 2 estilos de Kung Fu
Bruno Paulino
2
● Paginação
● Sumarização
● Cálculos
● Análise posicional entre linhas
● Análise de valor específico entre linhas
Roadmap - Necessidades técnicas e de negócio
3
SELECT
o.id, o.customer_id, o.status, o.total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC;
4
Estudo de Caso
5
Paginação - Antes
SELECT
o.id, o.customer_id, o.status, o.total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC
LIMIT 50 OFFSET 0;
SELECT COUNT(*)
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now();
6
Problemas
● Custo de Execução
● Nova query = Novo I/O
● Os dados são os mesmos!
SELECT
o.id, o.customer_id, o.status, o.total,
(
SELECT COUNT(*)
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
) total_rows
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC
LIMIT 50 OFFSET 150;
7
Eu sei resolver!
SELECT
o.id, o.customer_id, o.status, o.total,
(
SELECT COUNT(*)
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
) total_rows
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC
LIMIT 50 OFFSET 150;
8
Eu sei resolver!
9
Paginação - Depois
SELECT
o.id, o.customer_id, o.status, o.total,
COUNT(*) OVER() total_rows
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC
LIMIT 50 OFFSET 0;
blz:meetup ANTES +1s
blz:meetup DEPOIS +284ms
10
Window Functions
● Cálculos
● Relação entre linhas
● De agregação ou Analíticas
● Cláusula OVER()
● Espera o critério de relação para análise
11
Sumarização
SELECT
o.id, o.customer_id, o.status, o.total,
COUNT(*) OVER() total_rows,
SUM(o.total) OVER() sum_total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN '2018-08-01'::date AND now()
ORDER BY o.created_at DESC
LIMIT 50 OFFSET 150;
12
Dúvida de Negócio - Proporção de Frete
SELECT
i.order_id, i.sku, o.freight, i.price, o.sub_total,
i.quantity * i.price
/ SUM(i.quantity * i.price)
OVER(PARTITION BY i.order_id) proporcao_item,
o.freight * (
i.quantity * i.price
/ SUM(i.quantity * i.price)
OVER(PARTITION BY i.order_id)
) frete_proporcional
FROM raw_order.item i
JOIN raw_order.orders o ON i.order_id = o.id
WHERE i.order_id IN(1, 2)
ORDER BY 1
13
Dúvida de Negócio - Proporção de Frete
SELECT
i.order_id, i.sku, o.freight, i.price, o.sub_total,
i.quantity * i.price
/ SUM(i.quantity * i.price)
OVER(PARTITION BY i.order_id) proporcao_item,
o.freight * (
i.quantity * i.price
/ SUM(i.quantity * i.price)
OVER(PARTITION BY i.order_id)
) frete_proporcional
FROM raw_order.item i
JOIN raw_order.orders o ON i.order_id = o.id
WHERE i.order_id IN(1, 2)
ORDER BY 1
14
Relação entre as linhas
OVER(PARTITION BY critério)
SELECT
o.id, o.customer_id, o.status, o.total,
SUM(o.total)
OVER(PARTITION BY o.customer_id) customer_total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN
'2018-01-01'::date AND now()
AND o.customer_id IN(1, 2)
ORDER BY o.customer_id, o.created_at DESC;
id | customer | status | total | customer_total
----+----------+------------------+----------+---------------
17 | 1 | aguardando envio | 573.9 | 3409.36
16 | 1 | aguardando envio | 90.6 | 3409.36
15 | 1 | aguardando envio | 34.9 | 3409.36
14 | 1 | aguardando envio | 571.88 | 3409.36
13 | 1 | aguardando envio | 340.4 | 3409.36
12 | 1 | aguardando envio | 353.02 | 3409.36
11 | 1 | aguardando envio | 34.90 | 3409.36
10 | 1 | aguardando envio | 329.50 | 3409.36
7 | 1 | aguardando envio | 330.40 | 3409.36
6 | 1 | enviado | 31.80 | 3409.36
5 | 1 | enviado | 186.70 | 3409.36
4 | 1 | devolucao total | 120.40 | 3409.36
3 | 1 | enviado | 410.96 | 3409.36
18 | 2 | aguardando envio | 101.08 | 689.13
9 | 2 | aguardando envio | 180.71 | 689.13
8 | 2 | enviado | 108.70 | 689.13
2 | 2 | enviado | 51.92 | 689.13
1 | 2 | enviado | 246.72 | 689.13
15
Relação entre as linhas
OVER(PARTITION BY critério)
SELECT
o.id, o.customer_id, o.status, o.total,
SUM(o.total)
OVER(PARTITION BY o.customer_id) customer_total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN
'2018-01-01'::date AND now()
AND o.customer_id IN(1, 2)
ORDER BY o.customer_id, o.created_at DESC;
id | customer | status | total | customer_total
----+----------+------------------+----------+---------------
17 | 1 | aguardando envio | 573.9 | 4098.49
16 | 1 | aguardando envio | 90.6 | 4098.49
15 | 1 | aguardando envio | 34.9 | 4098.49
14 | 1 | aguardando envio | 571.88 | 4098.49
13 | 1 | aguardando envio | 340.4 | 4098.49
12 | 1 | aguardando envio | 353.02 | 4098.49
11 | 1 | aguardando envio | 34.90 | 4098.49
10 | 1 | aguardando envio | 329.50 | 4098.49
7 | 1 | aguardando envio | 330.40 | 4098.49
6 | 1 | enviado | 31.80 | 4098.49
5 | 1 | enviado | 186.70 | 4098.49
4 | 1 | devolucao total | 120.40 | 4098.49
3 | 1 | enviado | 410.96 | 4098.49
18 | 2 | aguardando envio | 101.08 | 4098.49
9 | 2 | aguardando envio | 180.71 | 4098.49
8 | 2 | enviado | 108.70 | 4098.49
2 | 2 | enviado | 51.92 | 4098.49
1 | 2 | enviado | 246.72 | 4098.49
16
Relação entre as linhas
OVER(PARTITION BY critério)
SELECT
o.id, o.customer_id, o.status, o.total,
SUM(o.total)
OVER(PARTITION BY o.customer_id) customer_total
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at BETWEEN
'2018-01-01'::date AND now()
AND o.customer_id IN(1, 2)
ORDER BY o.customer_id, o.created_at DESC;
id | customer | status | total | customer_total
----+----------+------------------+----------+---------------
17 | 1 | aguardando envio | 573.9 | 3409.36
16 | 1 | aguardando envio | 90.6 | 3409.36
15 | 1 | aguardando envio | 34.9 | 3409.36
14 | 1 | aguardando envio | 571.88 | 3409.36
13 | 1 | aguardando envio | 340.4 | 3409.36
12 | 1 | aguardando envio | 353.02 | 3409.36
11 | 1 | aguardando envio | 34.90 | 3409.36
10 | 1 | aguardando envio | 329.50 | 3409.36
7 | 1 | aguardando envio | 330.40 | 3409.36
6 | 1 | enviado | 31.80 | 3409.36
5 | 1 | enviado | 186.70 | 3409.36
4 | 1 | devolucao total | 120.40 | 3409.36
3 | 1 | enviado | 410.96 | 3409.36
18 | 2 | aguardando envio | 101.08 | 689.13
9 | 2 | aguardando envio | 180.71 | 689.13
8 | 2 | enviado | 108.70 | 689.13
2 | 2 | enviado | 51.92 | 689.13
1 | 2 | enviado | 246.72 | 689.13
17
Relação entre as linhas
OVER(ORDER BY critério)
SELECT
o.id, o.created_at::date, o.total,
SUM(o.total) OVER(ORDER BY o.created_at ASC) total_so_far,
SUM(o.total) OVER() total_geral
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at
BETWEEN '2018-01-01'::date AND now()
AND o.customer_id = 1
ORDER BY o.created_at ASC
18
Combinando...
SELECT
o.id, o.customer_id, o.created_at::date, o.total,
SUM(o.total) OVER(PARTITION BY o.customer_id ORDER BY o.created_at ASC) total_so_far,
SUM(o.total) OVER(PARTITION BY o.customer_id) total_geral
FROM raw_order.orders o
WHERE o.status != 'cancelado'
AND o.created_at
BETWEEN '2018-01-01'::date AND now()
AND o.customer_id IN(1, 2)
ORDER BY o.customer_id, o.created_at ASC
19
Outro exemplo...
SELECT
dt_event::date, nm_event, vl_event,
SUM(vl_event) OVER(ORDER BY dt_event ASC) vl_balance
FROM extrato
ORDER BY dt_event
Somente funcionam com cláusula OVER()
20
Funções Analíticas - Por Posição da Linha
SELECT
dt_event,
ROW_NUMBER() OVER(per_event_day) nu_row,
RANK() OVER(per_event_day) nu_rank,
DENSE_RANK() OVER(per_event_day) nu_dense_rank,
PERCENT_RANK() OVER(per_event_time) pc_rank
FROM extrato
WINDOW
per_event_time
AS(ORDER BY dt_event ASC),
per_event_day
AS(ORDER BY dt_event::date ASC)
ORDER BY dt_event
dt_event | nu_row | nu_rank | nu_dense_rank | pc_rank
---------------------+--------+---------+---------------+---------
2018-03-15 10:00:00 | 1 | 1 | 1 | 0
2018-03-15 12:00:00 | 2 | 1 | 1 | 0.25
2018-03-16 12:00:00 | 3 | 3 | 2 | 0.5
2018-03-16 20:00:00 | 4 | 3 | 2 | 0.75
2018-03-17 10:00:00 | 5 | 5 | 3 | 1
Recebem o campo que se deseja analisar
21
Funções Analíticas - Análise de Valor
SELECT
dt_event::date, vl_event, ROW_NUMBER() OVER(per_event_time) nu_row,
LAG(vl_event) OVER(per_event_time) vl_prev, LEAD(vl_event) OVER(per_event_time) vl_next,
FIRST_VALUE(vl_event) OVER(per_event_time) vl_first, LAST_VALUE(vl_event) OVER(per_event_time) vl_last
FROM extrato
WINDOW per_event_time AS(ORDER BY dt_event ASC)
ORDER BY dt_event
dt_event | vl_event | nu_row | vl_prev | vl_next | vl_first | vl_last
------------+----------+--------+---------+---------+----------+---------
2018-03-15 | 2000 | 1 | | -98 | 2000 | 2000
2018-03-15 | -98 | 2 | 2000 | -40 | 2000 | -98
2018-03-16 | -40 | 3 | -98 | -160 | 2000 | -40
2018-03-16 | -160 | 4 | -40 | 50 | 2000 | -160
2018-03-17 | 50 | 5 | -160 | | 2000 | 50
22
Na prática...
SELECT
dt_cotacao, vl_cotacao,
vl_cotacao
- LAG(vl_cotacao) OVER(per_date)
AS vl_variacao,
100 * (vl_cotacao
/ LAG(vl_cotacao) OVER(per_date) - 1
) AS pc_variacao
FROM petr3
WINDOW per_date
AS(ORDER BY dt_cotacao ASC)
ORDER BY 1 DESC
Still using Windows 3.1?
So why stick to SQL-92?
Markus Winand @ modern-sql.com
Conclusão
23
Obrigado
/paulinobruno
● https://modern-sql.com/
● https://use-the-index-luke.com/
24

More Related Content

PDF
New Query Optimizer features in MariaDB 10.3
PDF
Migrating one of the most popular e commerce platforms to mongodb
DOCX
Use shop
PPTX
Part1 of SQL Tuning Workshop - Understanding the Optimizer
PPTX
JKJ_T SQL project code samples
PPTX
Kudo Codefest: Faster data retrival with SQL query optimization
PDF
M|18 Understanding the Query Optimizer
PDF
A project on SQL (Amazon database)p.pdf
New Query Optimizer features in MariaDB 10.3
Migrating one of the most popular e commerce platforms to mongodb
Use shop
Part1 of SQL Tuning Workshop - Understanding the Optimizer
JKJ_T SQL project code samples
Kudo Codefest: Faster data retrival with SQL query optimization
M|18 Understanding the Query Optimizer
A project on SQL (Amazon database)p.pdf

Similar to Meetup Beleza na Web - Funções analíticas com SQL (18)

PDF
Performance e Produtividade: 2 Habilidades para Transformar seu Relacionament...
PPTX
Designing for DynamoDB - Serverless Sydney - Feb 2020
PDF
Performance e Produtividade: 2 Habilidades para Transformar seu Relacionament...
PPTX
SQL Query Optimization | SQL Query Optimization Techniques | SQL Basics | SQL...
PDF
kscope2013vst-130627142814-phpapp02.pdf
ODP
Oracle SQL Advanced
PPTX
SQL Tuning Methodology, Kscope 2013
PPT
Informix Warehouse Accelerator (IWA) features in version 12.1
DOCX
ADV DB SCREENSHOTS
PDF
Belajar SQL
PPTX
Adv.+SQL+PPT+final.pptx
PPT
Oracle tips and tricks
PDF
ANALYZE for Statements - MariaDB's hidden gem
PDF
The MySQL Query Optimizer Explained Through Optimizer Trace
PDF
Sql wksht-6
PDF
PPT -The MySQL Query optimizer trace .pdf
PDF
Common SQL Programming Mistakes
PPTX
Love Your Database Railsconf 2017
Performance e Produtividade: 2 Habilidades para Transformar seu Relacionament...
Designing for DynamoDB - Serverless Sydney - Feb 2020
Performance e Produtividade: 2 Habilidades para Transformar seu Relacionament...
SQL Query Optimization | SQL Query Optimization Techniques | SQL Basics | SQL...
kscope2013vst-130627142814-phpapp02.pdf
Oracle SQL Advanced
SQL Tuning Methodology, Kscope 2013
Informix Warehouse Accelerator (IWA) features in version 12.1
ADV DB SCREENSHOTS
Belajar SQL
Adv.+SQL+PPT+final.pptx
Oracle tips and tricks
ANALYZE for Statements - MariaDB's hidden gem
The MySQL Query Optimizer Explained Through Optimizer Trace
Sql wksht-6
PPT -The MySQL Query optimizer trace .pdf
Common SQL Programming Mistakes
Love Your Database Railsconf 2017
Ad

Recently uploaded (20)

PDF
KodekX | Application Modernization Development
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Machine learning based COVID-19 study performance prediction
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Empathic Computing: Creating Shared Understanding
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Big Data Technologies - Introduction.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
KodekX | Application Modernization Development
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Machine learning based COVID-19 study performance prediction
Network Security Unit 5.pdf for BCA BBA.
Encapsulation_ Review paper, used for researhc scholars
Advanced methodologies resolving dimensionality complications for autism neur...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Understanding_Digital_Forensics_Presentation.pptx
NewMind AI Weekly Chronicles - August'25 Week I
Programs and apps: productivity, graphics, security and other tools
Mobile App Security Testing_ A Comprehensive Guide.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Empathic Computing: Creating Shared Understanding
MIND Revenue Release Quarter 2 2025 Press Release
sap open course for s4hana steps from ECC to s4
Chapter 3 Spatial Domain Image Processing.pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Big Data Technologies - Introduction.pptx
Spectral efficient network and resource selection model in 5G networks
Ad

Meetup Beleza na Web - Funções analíticas com SQL

  • 2. ● 13 anos com desenvolvimento de software ● 2 certificações Java ● Formação DBA Oracle ● Responsável pelo BI da Beleza na Web ● Entusiasta pelo mercado financeiro e economia ● Formação em 2 estilos de Kung Fu Bruno Paulino 2
  • 3. ● Paginação ● Sumarização ● Cálculos ● Análise posicional entre linhas ● Análise de valor específico entre linhas Roadmap - Necessidades técnicas e de negócio 3
  • 4. SELECT o.id, o.customer_id, o.status, o.total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC; 4 Estudo de Caso
  • 5. 5 Paginação - Antes SELECT o.id, o.customer_id, o.status, o.total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC LIMIT 50 OFFSET 0; SELECT COUNT(*) FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now();
  • 6. 6 Problemas ● Custo de Execução ● Nova query = Novo I/O ● Os dados são os mesmos!
  • 7. SELECT o.id, o.customer_id, o.status, o.total, ( SELECT COUNT(*) FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ) total_rows FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC LIMIT 50 OFFSET 150; 7 Eu sei resolver!
  • 8. SELECT o.id, o.customer_id, o.status, o.total, ( SELECT COUNT(*) FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ) total_rows FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC LIMIT 50 OFFSET 150; 8 Eu sei resolver!
  • 9. 9 Paginação - Depois SELECT o.id, o.customer_id, o.status, o.total, COUNT(*) OVER() total_rows FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC LIMIT 50 OFFSET 0; blz:meetup ANTES +1s blz:meetup DEPOIS +284ms
  • 10. 10 Window Functions ● Cálculos ● Relação entre linhas ● De agregação ou Analíticas ● Cláusula OVER() ● Espera o critério de relação para análise
  • 11. 11 Sumarização SELECT o.id, o.customer_id, o.status, o.total, COUNT(*) OVER() total_rows, SUM(o.total) OVER() sum_total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-08-01'::date AND now() ORDER BY o.created_at DESC LIMIT 50 OFFSET 150;
  • 12. 12 Dúvida de Negócio - Proporção de Frete SELECT i.order_id, i.sku, o.freight, i.price, o.sub_total, i.quantity * i.price / SUM(i.quantity * i.price) OVER(PARTITION BY i.order_id) proporcao_item, o.freight * ( i.quantity * i.price / SUM(i.quantity * i.price) OVER(PARTITION BY i.order_id) ) frete_proporcional FROM raw_order.item i JOIN raw_order.orders o ON i.order_id = o.id WHERE i.order_id IN(1, 2) ORDER BY 1
  • 13. 13 Dúvida de Negócio - Proporção de Frete SELECT i.order_id, i.sku, o.freight, i.price, o.sub_total, i.quantity * i.price / SUM(i.quantity * i.price) OVER(PARTITION BY i.order_id) proporcao_item, o.freight * ( i.quantity * i.price / SUM(i.quantity * i.price) OVER(PARTITION BY i.order_id) ) frete_proporcional FROM raw_order.item i JOIN raw_order.orders o ON i.order_id = o.id WHERE i.order_id IN(1, 2) ORDER BY 1
  • 14. 14 Relação entre as linhas OVER(PARTITION BY critério) SELECT o.id, o.customer_id, o.status, o.total, SUM(o.total) OVER(PARTITION BY o.customer_id) customer_total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-01-01'::date AND now() AND o.customer_id IN(1, 2) ORDER BY o.customer_id, o.created_at DESC; id | customer | status | total | customer_total ----+----------+------------------+----------+--------------- 17 | 1 | aguardando envio | 573.9 | 3409.36 16 | 1 | aguardando envio | 90.6 | 3409.36 15 | 1 | aguardando envio | 34.9 | 3409.36 14 | 1 | aguardando envio | 571.88 | 3409.36 13 | 1 | aguardando envio | 340.4 | 3409.36 12 | 1 | aguardando envio | 353.02 | 3409.36 11 | 1 | aguardando envio | 34.90 | 3409.36 10 | 1 | aguardando envio | 329.50 | 3409.36 7 | 1 | aguardando envio | 330.40 | 3409.36 6 | 1 | enviado | 31.80 | 3409.36 5 | 1 | enviado | 186.70 | 3409.36 4 | 1 | devolucao total | 120.40 | 3409.36 3 | 1 | enviado | 410.96 | 3409.36 18 | 2 | aguardando envio | 101.08 | 689.13 9 | 2 | aguardando envio | 180.71 | 689.13 8 | 2 | enviado | 108.70 | 689.13 2 | 2 | enviado | 51.92 | 689.13 1 | 2 | enviado | 246.72 | 689.13
  • 15. 15 Relação entre as linhas OVER(PARTITION BY critério) SELECT o.id, o.customer_id, o.status, o.total, SUM(o.total) OVER(PARTITION BY o.customer_id) customer_total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-01-01'::date AND now() AND o.customer_id IN(1, 2) ORDER BY o.customer_id, o.created_at DESC; id | customer | status | total | customer_total ----+----------+------------------+----------+--------------- 17 | 1 | aguardando envio | 573.9 | 4098.49 16 | 1 | aguardando envio | 90.6 | 4098.49 15 | 1 | aguardando envio | 34.9 | 4098.49 14 | 1 | aguardando envio | 571.88 | 4098.49 13 | 1 | aguardando envio | 340.4 | 4098.49 12 | 1 | aguardando envio | 353.02 | 4098.49 11 | 1 | aguardando envio | 34.90 | 4098.49 10 | 1 | aguardando envio | 329.50 | 4098.49 7 | 1 | aguardando envio | 330.40 | 4098.49 6 | 1 | enviado | 31.80 | 4098.49 5 | 1 | enviado | 186.70 | 4098.49 4 | 1 | devolucao total | 120.40 | 4098.49 3 | 1 | enviado | 410.96 | 4098.49 18 | 2 | aguardando envio | 101.08 | 4098.49 9 | 2 | aguardando envio | 180.71 | 4098.49 8 | 2 | enviado | 108.70 | 4098.49 2 | 2 | enviado | 51.92 | 4098.49 1 | 2 | enviado | 246.72 | 4098.49
  • 16. 16 Relação entre as linhas OVER(PARTITION BY critério) SELECT o.id, o.customer_id, o.status, o.total, SUM(o.total) OVER(PARTITION BY o.customer_id) customer_total FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-01-01'::date AND now() AND o.customer_id IN(1, 2) ORDER BY o.customer_id, o.created_at DESC; id | customer | status | total | customer_total ----+----------+------------------+----------+--------------- 17 | 1 | aguardando envio | 573.9 | 3409.36 16 | 1 | aguardando envio | 90.6 | 3409.36 15 | 1 | aguardando envio | 34.9 | 3409.36 14 | 1 | aguardando envio | 571.88 | 3409.36 13 | 1 | aguardando envio | 340.4 | 3409.36 12 | 1 | aguardando envio | 353.02 | 3409.36 11 | 1 | aguardando envio | 34.90 | 3409.36 10 | 1 | aguardando envio | 329.50 | 3409.36 7 | 1 | aguardando envio | 330.40 | 3409.36 6 | 1 | enviado | 31.80 | 3409.36 5 | 1 | enviado | 186.70 | 3409.36 4 | 1 | devolucao total | 120.40 | 3409.36 3 | 1 | enviado | 410.96 | 3409.36 18 | 2 | aguardando envio | 101.08 | 689.13 9 | 2 | aguardando envio | 180.71 | 689.13 8 | 2 | enviado | 108.70 | 689.13 2 | 2 | enviado | 51.92 | 689.13 1 | 2 | enviado | 246.72 | 689.13
  • 17. 17 Relação entre as linhas OVER(ORDER BY critério) SELECT o.id, o.created_at::date, o.total, SUM(o.total) OVER(ORDER BY o.created_at ASC) total_so_far, SUM(o.total) OVER() total_geral FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-01-01'::date AND now() AND o.customer_id = 1 ORDER BY o.created_at ASC
  • 18. 18 Combinando... SELECT o.id, o.customer_id, o.created_at::date, o.total, SUM(o.total) OVER(PARTITION BY o.customer_id ORDER BY o.created_at ASC) total_so_far, SUM(o.total) OVER(PARTITION BY o.customer_id) total_geral FROM raw_order.orders o WHERE o.status != 'cancelado' AND o.created_at BETWEEN '2018-01-01'::date AND now() AND o.customer_id IN(1, 2) ORDER BY o.customer_id, o.created_at ASC
  • 19. 19 Outro exemplo... SELECT dt_event::date, nm_event, vl_event, SUM(vl_event) OVER(ORDER BY dt_event ASC) vl_balance FROM extrato ORDER BY dt_event
  • 20. Somente funcionam com cláusula OVER() 20 Funções Analíticas - Por Posição da Linha SELECT dt_event, ROW_NUMBER() OVER(per_event_day) nu_row, RANK() OVER(per_event_day) nu_rank, DENSE_RANK() OVER(per_event_day) nu_dense_rank, PERCENT_RANK() OVER(per_event_time) pc_rank FROM extrato WINDOW per_event_time AS(ORDER BY dt_event ASC), per_event_day AS(ORDER BY dt_event::date ASC) ORDER BY dt_event dt_event | nu_row | nu_rank | nu_dense_rank | pc_rank ---------------------+--------+---------+---------------+--------- 2018-03-15 10:00:00 | 1 | 1 | 1 | 0 2018-03-15 12:00:00 | 2 | 1 | 1 | 0.25 2018-03-16 12:00:00 | 3 | 3 | 2 | 0.5 2018-03-16 20:00:00 | 4 | 3 | 2 | 0.75 2018-03-17 10:00:00 | 5 | 5 | 3 | 1
  • 21. Recebem o campo que se deseja analisar 21 Funções Analíticas - Análise de Valor SELECT dt_event::date, vl_event, ROW_NUMBER() OVER(per_event_time) nu_row, LAG(vl_event) OVER(per_event_time) vl_prev, LEAD(vl_event) OVER(per_event_time) vl_next, FIRST_VALUE(vl_event) OVER(per_event_time) vl_first, LAST_VALUE(vl_event) OVER(per_event_time) vl_last FROM extrato WINDOW per_event_time AS(ORDER BY dt_event ASC) ORDER BY dt_event dt_event | vl_event | nu_row | vl_prev | vl_next | vl_first | vl_last ------------+----------+--------+---------+---------+----------+--------- 2018-03-15 | 2000 | 1 | | -98 | 2000 | 2000 2018-03-15 | -98 | 2 | 2000 | -40 | 2000 | -98 2018-03-16 | -40 | 3 | -98 | -160 | 2000 | -40 2018-03-16 | -160 | 4 | -40 | 50 | 2000 | -160 2018-03-17 | 50 | 5 | -160 | | 2000 | 50
  • 22. 22 Na prática... SELECT dt_cotacao, vl_cotacao, vl_cotacao - LAG(vl_cotacao) OVER(per_date) AS vl_variacao, 100 * (vl_cotacao / LAG(vl_cotacao) OVER(per_date) - 1 ) AS pc_variacao FROM petr3 WINDOW per_date AS(ORDER BY dt_cotacao ASC) ORDER BY 1 DESC
  • 23. Still using Windows 3.1? So why stick to SQL-92? Markus Winand @ modern-sql.com Conclusão 23