Category Archives: SQL

Cross Apply no Sql Server

Precisava criar um relatório que listasse a média das 3 primeiras vendas de clientes novos do ano atual (2018).

A query então deve conter 2 tabelas: cliente e pedidos. O filtro do cliente e dos pedidos é básico. O difícil é fazer com que os pedidos recebam o código do cliente do Select e aplicá-lo na query que traz os pedidos.

A princípio tentei fazer um Join, depois uma subquery mas por conta da operador TOP não conseguia. Logicamente o TOP 3 retornaria apenas três registros da tabela pedido e não três pedidos da tabela pedido para cada cliente da query principal.

Pesquisando um pouco eu cheguei a uma query com dois joins que não deu muito certo, mas a lógica até que é boa:

SELECT
A1_COD,
Z7.Z7_CONSULT,
Z7.Z7_NUM,
Z7.Z7_DTFECHA,
B.*
FROM
SA1010 A1
LEFT JOIN (SELECT TOP 3 Z7_NUM, Z7_CONSULT FROM SZ7010 WHERE D_E_L_E_T_ = '' AND Z7_STATUS = 'F' ORDER BY Z7_DTFECHA) B ON A1.A1_COD = B.Z7_CONSULT
LEFT JOIN SZ7010 Z7 ON Z7.Z7_NUM = B.Z7_NUM
WHERE
A1.D_E_L_E_T_ = '' AND
A1.A1_DTCAD > 20180101 AND
A1.A1_STATUS = 1
ORDER BY
A1.A1_COD

Porém não funcionou. : (

A solução foi a utilizar o operador CROSS APPLY, que utiliza uma query como entrada para outra e as uni. Analisando o problema das novatas em questão fica fácil entender o funcionamento. Veja a query:

SELECT
A1_COD,
A1_NOME,
A1_DTCAD,
CA.*
FROM
SA1010 A1
CROSS APPLY (
SELECT TOP 3
Z7_NUM,
Z7_CONSULT,
Z7_QTDCOMD,
Z7_REGIAO,
Z7_DTFECHA
FROM
SZ7010 B
WHERE
B.D_E_L_E_T_ = '' AND
B.Z7_STATUS = 'F' AND
B.Z7_SERIE <> 'DIR' AND
A1.A1_COD = B.Z7_CONSULT
ORDER BY
Z7_DTFECHA) CA
WHERE
A1.D_E_L_E_T_ = '' AND
A1.A1_DTCAD > 20180101 AND
A1.A1_STATUS = 1
ORDER BY
A1.A1_COD

A query então traz os 3 primeiros pedidos para cada cliente retornado na query inicial e junta os resultados.

109244 <<NOME>> 20180102 842355 109244 23 000122 20180203
109244 <<NOME>> 20180102 844817 109244 45 000122 20180312
109244 <<NOME>> 20180102 862112 109244 54 000122 20180419
109255 <<NOME>> 20180102 839520 109255 17 000072 20180204
109255 <<NOME>> 20180102 854113 109255 28 000072 20180313
109255 <<NOME>> 20180102 861392 109255 42 000072 20180417
109260 <<NOME>> 20180105 838082 109260 25 000093 20180205
109260 <<NOME>> 20180105 851091 109260 41 000093 20180314
109260 <<NOME>> 20180105 863113 109260 41 000093 20180418

Depois disso apenas alterei a query para que ao invés dos três pedidos retornasse a média de peças vendidas e pronto. Relatório concluido com performance e acuracidade.

Seguem dois links que tratam do operador Cross Apply que me ajudaram:

https://www.tutorialti.com/2015/02/o-que-e-cross-apply-sql-server.html

http://blog.dbaacademy.com.br/sql-server-cross-apply-e-cross-join/

Espero ter ajudado e até!