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 / 106948
Accepted
ΩmegaMan
ΩmegaMan
Asked: 2015-07-15 11:31:16 +0800 CST2015-07-15 11:31:16 +0800 CST 2015-07-15 11:31:16 +0800 CST

Determinar registros de lacunas, preencher e retornar o resultado

  • 772

O código de trabalho a seguir tem como alvo o SQL-Server 2012 e eu destilei o problema real em um cenário administrável com o exemplo de código mostrado abaixo também apresentado em SQL Fiddle.

Busco feedback sobre as melhores práticas de uso de CTEs e tabelas temporárias e gostaria de saber se o seguinte poderia ser simplificado como tal.

( Observe que isso também foi solicitado na revisão de código ( processo de relatório de inserção de registros de lacunas ) sem respostas até o momento.)

Premissa

Existem duas Tabelas que abrigam eventos com registro de data e hora para Agentes e Gerenciamento. Um relatório será executado na tabela de agentes. Mas dentro da tabela Agente, se houver intervalo(s) de eventos de mais de 5 horas, o relatório resultante deverá ser preenchido a partir da tabela de eventos de gerenciamento para esse intervalo.

Agente

CREATE TABLE AgentInteractions
(
   [Event]      VARCHAR(12) NOT NULL, 
   [Timestamp] [DateTime] NOT NULL
);


INSERT INTO dbo.AgentInteractions( Event, TimeStamp  )
VALUES ( 'Alpha', '24-Jan-2018 3:04:00 PM' ),
       ( 'Beta', '24-Jan-2018 10:04:00 PM' ),  -- Gap 7 hours
       ( 'Omega', '25-Jan-2018 2:04:00 AM' );  -- No Gap

Gestão

CREATE TABLE ManagementInteractions
(
  [Event]      VARCHAR(12) NOT NULL, 
  [Timestamp] [DateTime] NOT NULL
);


INSERT INTO dbo.ManagementInteractions( Event, TimeStamp  )
VALUES ( '5pm',      '24-Jan-2018 5:00:00 PM' ),  -- Gap Filler #1
       ( '8pm',      '24-Jan-2018 8:00:00 PM' ),  -- Gap Filler #2
       ( 'Midnight', '25-Jan-2018 12:00:00 AM' ); -- Not used

Relatório inicial (ou primeira etapa)

Com o seguinte sql que coloca o relatório na tabela temporária, ele calcula a diferença de tempo entre as linhas e configura uma sequência que não estava presente nos dados de origem.

CTE para tabela temporária

IF OBJECT_ID('tempdb..#Actions') IS NOT NULL DROP TABLE #Actions;

WITH AgentActions AS 
( SELECT  ROW_NUMBER() OVER ( ORDER BY [Timestamp] ) AS [Sequence], -- Create an index number ordered by time.
          Event ,
          Timestamp
  FROM  AgentInteractions
)
SELECT  CAST('Agent' AS VARCHAR(20)) AS [Origin] ,
            AgentActions.Sequence ,
            AgentActions.Event ,
            ( SELECT    Other.Timestamp
              FROM      AgentActions Other
              WHERE     Other.Sequence = AgentActions.Sequence - 1
            ) AS Previous ,
            AgentActions.Timestamp ,
            ISNULL(DATEDIFF(HOUR,
                            ( SELECT    Other.Timestamp
                              FROM      AgentActions Other
                              WHERE     Other.Sequence = AgentActions.Sequence - 1), 
                            AgentActions.Timestamp), 
                            0) AS TimeFromLastPoint
    INTO    #Actions
    FROM    AgentActions;

Resultado de um select into #Actions, observe o intervalo de 7 horas:

insira a descrição da imagem aqui

Determinar lacunas

O sql a seguir determina as lacunas e insere os registros da tabela de gerenciamento que preenchem a lacuna.

Inserir eventos de gerenciamento nas lacunas

WITH Gaps AS 
( SELECT   AC.Origin ,
           AC.Sequence ,
           AC.Event ,
           AC.Previous ,
           AC.Timestamp ,
           AC.TimeFromLastPoint
  FROM     #Actions AC
  WHERE    AC.TimeFromLastPoint > 5
)
INSERT  INTO #Actions ( [Origin] , [Event] , [Timestamp] , TimeFromLastPoint)
            SELECT  'Management' ,
                    [Event] ,
                    [Timestamp] ,
                    0                      -- We will figure this out after the insert.
            FROM    ManagementInteractions MAN
            WHERE   EXISTS ( SELECT *
                             FROM   Gaps
                             WHERE  MAN.Timestamp BETWEEN Gaps.Previous
                                                  AND     Gaps.Timestamp );

SELECT Origin , Sequence , Event , Previous , Timestamp , TimeFromLastPoint 
FROM #Actions ORDER BY Timestamp;

Resultado da seleção.

insira a descrição da imagem aqui

Relatório final

O relatório final faz o que foi feito na etapa 1, ele resequencia e determina as durações de tempo entre todos os pontos.

CTE Deja-vu Relatório Final

WITH Combined AS 
( 
   SELECT Origin,
          ROW_NUMBER() OVER ( ORDER BY [Timestamp] ) AS [Sequence], -- Create an index number ordered by time.
          Event ,
          Timestamp
    FROM  #Actions
)
SELECT  Combined.Origin,
        Combined.Sequence ,
        Combined.Event ,
        ( SELECT    Other.Timestamp
          FROM      Combined Other
          WHERE     Other.Sequence = Combined.Sequence - 1
        ) AS Previous ,
        Combined.Timestamp ,
        ISNULL(DATEDIFF(HOUR,
                        ( SELECT    Other.Timestamp
                          FROM      Combined Other
                          WHERE     Other.Sequence = Combined.Sequence
                                    - 1
                        ), Combined.Timestamp), 0) AS TimeFromLastPoint

FROM  Combined;

Aqui estão os resultados

insira a descrição da imagem aqui

Resumo

Alguma das etapas pode ser combinada ou há alguma prática que devo usar ou evitar com o código sql acima?

sql-server sql-server-2012
  • 1 1 respostas
  • 701 Views

1 respostas

  • Voted
  1. Best Answer
    Geoff Patterson
    2015-07-15T12:47:25+08:002015-07-15T12:47:25+08:00

    Eu acho que a abordagem que você criou é muito boa. Aqui está uma simplificação proposta que evita a junção automática dbo.AgentInteractionsusando a nova função LAG do SQL Server 2012 , bem como CTEs para destilar a lógica em uma única consulta (também no SQL Fiddleformulário).

    WITH AgentActions AS (
        -- Sequence the agent actions
        SELECT a.Event,
            LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC) AS Previous,
            a.TimeStamp,
            DATEDIFF(HOUR, LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC), a.TimeStamp) AS TimeFromLastPoint
        FROM dbo.AgentInteractions a
    ),
    allActionsToReport AS (
        --  Agent action
        SELECT 'Agent' AS Origin, a.Event, a.TimeStamp
        FROM AgentActions a
        UNION ALL
        -- Any management actions during a gap of > 5 hours between agent interactions
        SELECT 'Management' AS Origin, m.event, m.TimeStamp
        FROM AgentActions a
        JOIN ManagementInteractions m
            ON m.TimeStamp BETWEEN a.Previous AND a.TimeStamp
        WHERE a.TimeFromLastPoint > 5
    )
    -- For all actions (with gaps already filled), perform final sequencing
    SELECT a.Origin,
        ROW_NUMBER() OVER (ORDER BY a.TimeStamp ASC) AS Sequence,
        a.Event,
        LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC) AS Previous,
        a.TimeStamp,
        ISNULL(DATEDIFF(HOUR, LAG(a.TimeStamp, 1) OVER (ORDER BY TimeStamp ASC), a.TimeStamp), 0) AS TimeFromLastPoint
    FROM allActionsToReport a
    

    Olhando para o plano de consulta para esta versão de consulta única, ele faz exatamente o que você esperaria: classificar as ações do agente por registro de data e hora, preencher as lacunas acessando as ações de gerenciamento e, em seguida, classificar esse conjunto combinado de ações resultantes para fazer o sequenciamento final:

    insira a descrição da imagem aqui

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • 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 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