Eu tenho um Banco de Dados SQL do Azure, uma Tabela que possui 3 Colunas Relevantes: Marca, ID e Mês/Ano e uma Tabela Temporária que simplesmente lista o Mês/Ano com um ID.
A tabela mostra uma lista de todos os IDs que estavam ativos naquele determinado mês.
Mês/Ano é uma coluna de carimbo de data, com a data como o primeiro do Mês. A coluna ID é apenas um ID.
O objetivo é ter uma saída que, para cada mês, mostre a contagem de todos os registros que estavam ativos neste mês, mas não ativos no mês seguinte (Churn) e IDs que não estavam ativos no mês anterior, mas estavam ativos neste mês (Novo) e ter estes agrupados por marca e mês assim:
Marca | Churn | Novo | Mês
1 | 10 | 12 | 01-12-2019
2 | 11 | 9 | 01-12-2019
Devo também observar que Table1 tem 19 milhões de linhas.
Tentei o código abaixo:
Declare @Id int
declare @my date
set @Id = 300
set @my = '2019-12-01'
select t1.[brand],
count(c.[ID]) as [churn],
count(n.[ID]) as [new],
t1.[month/year]
from Table1 T1
left join Table1 c on
c.[ID] = t1.[ID] and c.[ID] not in (select [ID] from Table1 where [Month/Year] = (select [month/year] from Temp_Date where id = (@Id +1)))
left join Table1 n on
n.[ID] = T1.[ID] and n.[ID] not in (select [ID] from Table1 where [Month/Year] = (select [month/year] from Temp_Date where id = (@Id -1)))
where t1.[Month/Year] = @my
group by t1.[Brand], t1.[Month/Year]
Que apesar de ter produzido uma saída, acho que não estava certo e demorou muito, provavelmente devido ao meu uso liberal de Sub-consultas em Joins.
Minha pergunta é dupla - alguém pode ajudar de uma maneira melhor para contar o número de linhas e juntá-las e existe uma maneira melhor de fazer isso sem tantas subconsultas?
Em geral, você deve incluir os scripts que geram seus esquemas de tabela e os preenche com dados. (Também para questões de desempenho, você deve incluir o plano de execução também.) Eu não poderia fazer muitos testes sem dados reais, mas acredito que esta consulta deve melhorar o desempenho que você está vendo:
Isso também é muito mais simples (tanto para o desenvolvedor ler quanto para o SQL Server analisar) do que um monte de subconsultas. Você provavelmente está certo de que a junção adicional desnecessária às subconsultas é uma fonte de seus problemas de desempenho (mas não posso verificar isso sem ver o plano de execução ).
O que a consulta acima faz é usar a
LEFT JOIN
para Table1 em si mesmo duas vezes (uma vez para oPreviousMonth
e uma vez para oNextMonth
)ID
para obter todos os registros que correspondem e não correspondem aoCurrentMonth
. Em seguida, usando aSUM()
função de agregação com umaCASE
instrução dentro dela, podemos resumir apenas osNULLs
(casos em que oID
doCurrentMonth
não existia noPreviousMonth
eNextMonth
) para obter as contagens para oNew
eChurn
, agrupadas peloBrand
eMonthYear
doCurrentMonth
.Se
DAY(date)
for sempre 1, então você pode usar algo comoSe você precisar apenas comuná-los, use a consulta semelhante à anterior no CTE e agregue-a na consulta principal.