AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 283286
Accepted
TheDemonLord
TheDemonLord
Asked: 2021-01-15 17:27:47 +0800 CST2021-01-15 17:27:47 +0800 CST 2021-01-15 17:27:47 +0800 CST

Contar linhas que existem antes e não depois e depois, mas não antes

  • 772

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?

sql-server join
  • 2 2 respostas
  • 144 Views

2 respostas

  • Voted
  1. Best Answer
    J.D.
    2021-01-15T19:08:36+08:002021-01-15T19:08:36+08:00

    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:

    DECLARE @my DATE = '2019-12-01'
    DECLARE @nextMonthYear DATE = DATEADD(MONTH, 1, @my)
    DECLARE @prevMonthYear DATE = DATEADD(MONTH, -1, @my)
    
    SELECT CurrentMonth.Brand, SUM(CASE WHEN NextMonth.ID IS NULL THEN 1 ELSE 0 END) AS Churn, SUM(CASE WHEN PreviousMonth.ID IS NULL THEN 1 ELSE 0 END) AS New, CurrentMonth.MonthYear
    FROM Table1 AS CurrentMonth
    LEFT JOIN Table1 AS NextMonth
        ON NextMonth.MonthYear = @nextMonthYear
        AND CurrentMonth.ID = NextMonth.ID  
    LEFT JOIN Table1 AS PreviousMonth
        ON PreviousMonth.MonthYear = @prevMonthYear
        AND CurrentMonth.ID = PreviousMonth.ID  
    WHERE CurrentMonth.MonthYear = @my
    GROUP BY CurrentMonth.Brand, CurrentMonth.MonthYear
    

    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 JOINpara Table1 em si mesmo duas vezes (uma vez para o PreviousMonthe uma vez para o NextMonth) IDpara obter todos os registros que correspondem e não correspondem ao CurrentMonth. Em seguida, usando a SUM()função de agregação com uma CASEinstrução dentro dela, podemos resumir apenas os NULLs(casos em que o IDdo CurrentMonthnão existia no PreviousMonthe NextMonth) para obter as contagens para o Newe Churn, agrupadas pelo Brande MonthYeardo CurrentMonth.

    • 1
  2. Akina
    2021-01-15T20:44:46+08:002021-01-15T20:44:46+08:00

    Se DAY(date)for sempre 1, então você pode usar algo como

    SELECT *, 
           CASE WHEN LAG([id]) OVER (ORDER BY [Month/Year] RANGE BETWEEN FOLLOWING 1 MONTH AND FOLLOWING 1 MONTH) IS NULL 
                THEN 'New' 
                WHEN LEAD([id]) OVER (ORDER BY [Month/Year] RANGE BETWEEN FOLLOWING 1 MONTH AND FOLLOWING 1 MONTH) IS NULL 
                THEN 'Churn'
                ELSE '' 
                END AS [state]
    FROM [src table]
    

    Se você precisar apenas comuná-los, use a consulta semelhante à anterior no CTE e agregue-a na consulta principal.

    • 0

relate perguntas

  • Qual é a diferença entre um INNER JOIN e um OUTER JOIN?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como é a saída de uma instrução JOIN?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve