Removendo função com cross apply
Olá pessoal, tudo bem? Hoje gostaria de compartilhar meu primeiro Tuning na nova empresa, ter conseguido realizar essa melhoraria pro cliente foi muito gratificante pra mim e me deixou muito feliz, então decidi compartilhar com vocês.
Antes de começar a explicar vamos montar o ambiente para teste. Irei disponibilizar 2 scripts, um para criar as tabelas que irei utilizar e outro para criar a função do teste.
Obs: Esse script de criação de tabela, foi feito pelo Fabiano Amorim, uma lenda do tuning.
Segue blog dele: https://blogfabiano.com/
Outra observação importante é que aqui não estarei explicando profundamente sobre o operador apply para quem quiser conhecer sobre, leia esse artigo do Marcio Junior um cara que na minha opinião é um dos melhores em tuning do Brasil.
Segue blog dele com o post: https://vulgomarcio.home.blog/2019/08/05/voce-conhece-o-operador-apply/
Agora vamos ao cenário, para replicar o cenário do cliente peguei duas tabelas famosas do banco Northwind que o Fabiano criou uma versão BIG, ou seja com muitos dados para explicar o que o cliente estava querendo fazer.
customersbig = dados do cliente
ordersbig = Descrição das vendas
Basicamente precisamos pegar a última venda do cliente por determinada data.
Essa é a query com a função
select
a.CityID
,a.CompanyName
,a.ContactName
,b.value
,B.orderid
,a.CustomerID
from customersbig a
inner join ordersbig b
on a.customerid= b.customerid
where orderid = [dbo].menor_venda_por_data(a.customerid,'2021-05-11')
Essa query aqui rodou em 13 segundos:
select
a.CityID
,a.CompanyName
,a.ContactName
,b.value
from customersbig a
join ordersbig b
on a.customerid= b.customerid
cross apply (
select IsNull(Min(orderid),-1) as orderid from ordersbig b
where a.customerid= b.customerid
and orderdate = '2021-05-11'
) as d
where d.orderid = b.orderid
https://docs.microsoft.com/pt-br/dotnet/framework/data/adonet/sql/linq/downloading-sample-databases
Pessoal o Marcio Junior me mandou essa solução, reparem no order by, essa sintaxe é muito útil e nunca vi sendo utlizada.
ResponderExcluir;WITH CTE
AS
(
SELECT TOP 1 WITH TIES
b1.Value,
CustomerID
FROM
OrdersBig b1
WHERE
OrderDate = '2021-05-11'
ORDER BY
ROW_NUMBER() OVER(PARTITION BY b1.CustomerID ORDER BY orderid)
)
SELECT
a.CityID,
a.CompanyName,
a.ContactName,
b.Value
FROM
customersbig a
INNER JOIN CTE B ON a.CustomerID = b.CustomerID