none
Retornos NULL nos últimos 30 minutos RRS feed

  • Dotaz

  • Boa tarde.

    Utilizo o SQL Server 2017 e estou precisando do seguinte select:

    Tenho uma tabela na qual existem 2 colunas: 1ª DataInicio e 2 DataFim

    Quando uma remessa começa a ser processada, insere nessa coluna (DataInicio) a hora que iniciou e quando termina, insere a data de término na coluna (DataFim).

    Durante o processamento, a coluna DataFim fica com NULL.

    Eu preciso fazer um select que me traga quando a coluna DataFim ficar como NULL por mais de 30 minutos a partir da DataInicio.

    pondělí 26. srpna 2019 17:28

Odpovědi

  • Boa tarde,

    Tente assim:

    with cte_tempo_decorrido as
     (
       select *,
             datediff (minute,DataInicio ,getdate()) as Tempo_decorrido
       from Sua_Tabela where DataFim is null
    )
    select * from cte_tempo_decorrido
    	where Tempo_decorrido > 30


    pondělí 26. srpna 2019 18:01

  • Eu preciso fazer um select que me traga quando a coluna DataFim ficar como NULL por mais de 30 minutos a partir da DataInicio.

    Raphael, essa consulta vai ser processada periodicamente e você deseja saber quais remessas estão em processamento há mais de 30 minutos ou deseja saber quais remessas demoraram mais de 30 minutos?

    Para o primeiro caso, eis uma sugestão:

    -- código #1
    SELECT remessa, DataInicio, 
    datediff (minute, DataInicio, current_timestamp) [Processando há (minutos)] from tbTEMP where DataFim is null and DataInicio < dateadd (minute, -30, current_timestamp);

    Não testei; pode conter erro(s).

    Observe que o código acima é sargable. Detalhes no artigo “Construindo códigos T-SQL eficientes”.

    ---  

    Mas se o que necessita é saber quais remessas demoraram mais de 30 minutos, eis outra sugestão:

    -- código #2
    SELECT remessa, DataInicio, DataFim,
           datediff (minute, DataInicio, DataFim) [Processado em (minutos)]
    from tbTEMP where DataFim > dateadd (minute, 30, DataInicio);

    Não testei; pode conter erro(s).



    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Označen jako odpověď Raphael Lage pondělí 26. srpna 2019 19:29
    • Upravený José Diz úterý 3. září 2019 22:26
    pondělí 26. srpna 2019 19:06
  • SELECT DataInicio, DiarioID, Fg_Status,    
           DATEDIFF (MINUTE, DataInicio, CURRENT_TIMESTAMP) [Processando há (minutos)]
    FROM TG_Gerenciador_FULL
    WHERE DataFim IS NULL
            AND DataInicio < DATEADD (MINUTE, -30, CURRENT_TIMESTAMP)
    AND Fg_Status = 0 OR Fg_Status = 1
    ORDER BY DataInicio DESC

    Ok.

    A causa está aqui: "OR Fg_Status = 1". Basta que a coluna Fg_Status esteja 1 que será retornada linha, mesmo que não seja caso de processando há mais de 30 minutos.

    Sugiro que substitua por

           AND (Fg_Status = 0 OR Fg_Status = 1)

         


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Označen jako odpověď Raphael Lage úterý 3. září 2019 22:46
    • Upravený José Diz úterý 3. září 2019 23:17
    úterý 3. září 2019 22:09

Všechny reakce

  • Boa tarde,

    Tente assim:

    with cte_tempo_decorrido as
     (
       select *,
             datediff (minute,DataInicio ,getdate()) as Tempo_decorrido
       from Sua_Tabela where DataFim is null
    )
    select * from cte_tempo_decorrido
    	where Tempo_decorrido > 30


    pondělí 26. srpna 2019 18:01
  • Raphael,

    Basicamente você poderia fazer uso das funções DateAdd() e DateDiff() em conjunto com o operador Case ou função IIF(), veja o exemplo:

    Create Table TabelaRemessa (Codigo Int Primary Key Identity(1,1), DataInicial DateTime Default GetDate(), DataFinal DateTime Null) Go Insert Into TabelaRemessa (DataInicial, DataFinal) Values (GetDate(), Null), (GetDate()+2, Null), (GetDate()+4, Null) Go

    -- Analisando se o valor da coluna DataFinal esta Null -- Select Codigo, DataInicial, Case When (DataFinal Is NULL) Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataFinal Is Null, DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go


    Ressalto que este é um exemplo de Código, um esboço, faça uma análise de qual abordagem poderia ser melhor, destaco que a função IIF() ela vai levar em consideração a condição aplicada a ela processando linha a linha, o que poderá atrapalhar a performance, como também, o Case, que em contra partida apresenta um comportamento mais aceitável depedendo do volume de dados.

    Neste outro trecho aqui, você vai poder justamente analisar a diferença entre as datas com base nos 30 minutos:

    -- Aplicando os trinta minutos após a passagem do tempo --

    Select Codigo, DataInicial, Case When (DataInicial < dateadd (minute, -30, GetDate()))

    Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataInicial < dateadd (minute, -30, GetDate())

    , DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]




    pondělí 26. srpna 2019 18:02
    Moderátor

  • Eu preciso fazer um select que me traga quando a coluna DataFim ficar como NULL por mais de 30 minutos a partir da DataInicio.

    Raphael, essa consulta vai ser processada periodicamente e você deseja saber quais remessas estão em processamento há mais de 30 minutos ou deseja saber quais remessas demoraram mais de 30 minutos?

    Para o primeiro caso, eis uma sugestão:

    -- código #1
    SELECT remessa, DataInicio, 
    datediff (minute, DataInicio, current_timestamp) [Processando há (minutos)] from tbTEMP where DataFim is null and DataInicio < dateadd (minute, -30, current_timestamp);

    Não testei; pode conter erro(s).

    Observe que o código acima é sargable. Detalhes no artigo “Construindo códigos T-SQL eficientes”.

    ---  

    Mas se o que necessita é saber quais remessas demoraram mais de 30 minutos, eis outra sugestão:

    -- código #2
    SELECT remessa, DataInicio, DataFim,
           datediff (minute, DataInicio, DataFim) [Processado em (minutos)]
    from tbTEMP where DataFim > dateadd (minute, 30, DataInicio);

    Não testei; pode conter erro(s).



    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Označen jako odpověď Raphael Lage pondělí 26. srpna 2019 19:29
    • Upravený José Diz úterý 3. září 2019 22:26
    pondělí 26. srpna 2019 19:06
  • Raphael,

    Basicamente você poderia fazer uso das funções DateAdd() e DateDiff() em conjunto com o operador Case ou função IIF(), veja o exemplo:

    Create Table TabelaRemessa (Codigo Int Primary Key Identity(1,1), DataInicial DateTime Default GetDate(), DataFinal DateTime Null) Go Insert Into TabelaRemessa (DataInicial, DataFinal) Values (GetDate(), Null), (GetDate()+2, Null), (GetDate()+4, Null) Go

    -- Analisando se o valor da coluna DataFinal esta Null -- Select Codigo, DataInicial, Case When (DataFinal Is NULL) Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataFinal Is Null, DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go


    Ressalto que este é um exemplo de Código, um esboço, faça uma análise de qual abordagem poderia ser melhor, destaco que a função IIF() ela vai levar em consideração a condição aplicada a ela processando linha a linha, o que poderá atrapalhar a performance, como também, o Case, que em contra partida apresenta um comportamento mais aceitável depedendo do volume de dados.

    Neste outro trecho aqui, você vai poder justamente analisar a diferença entre as datas com base nos 30 minutos:

    -- Aplicando os trinta minutos após a passagem do tempo --

    Select Codigo, DataInicial, Case When (DataInicial < dateadd (minute, -30, GetDate()))

    Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataInicial < dateadd (minute, -30, GetDate())

    , DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]



    Obrigado pelo retorno.

    Não sei se fiz algo errado (não tenho muito conhecimento em SQL) mas não serviu exatamente para o que eu preciso.

    Preciso que o select só me traga as remessas que estão em processamento há mais de 30 minutos.


    pondělí 26. srpna 2019 19:12

  • Eu preciso fazer um select que me traga quando a coluna DataFim ficar como NULL por mais de 30 minutos a partir da DataInicio.

    Raphael, essa consulta vai ser processada periodicamente e você deseja saber quais remessas estão em processamento há mais de 30 minutos ou deseja saber quais remessas demoraram mais de 30 minutos?

    Para o primeiro caso, eis uma sugestão:

    -- código #1
    SELECT remessa, DataInicio, 
    datediff (minute, DataInicio, current_timestamp) [Processando há (minutos)] from tbTEMP where DataFim is null and DataInicio < dateadd (minute, -30, current_timestamp);

    Não testei; pode conter erro(s).

    Observe que o código acima é sargable. Detalhes no artigo “Construindo códigos T-SQL eficientes”.

    ---  

    Mas se o que necessita é saber quais remessas demoraram mais de 30 minutos, eis outra sugestão:

    -- código #2
    SELECT remessa, DataInicio, DataFim,
           datediff (minute, DataInicio, DataFim) [Processado em (minutos)]
    from tbTEMP where DataFim > dateadd (minute, 30, DataInicio);

    Não testei; pode conter erro(s).

      

    Lembre-se de marcar esta resposta se ela te ajudou a resolver o problema.


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    José, o primeiro código serviu perfeitamente. Como atualmente eu não tenho nenhuma remessa que caia nessa condição e o seu código não me trouxe nada, acredito que esteja correto. Os outros traziam alguma informação, dessa maneira já sabia que estava errado.

    Muito obrigado


    pondělí 26. srpna 2019 19:33
  • Raphael,

    Basicamente você poderia fazer uso das funções DateAdd() e DateDiff() em conjunto com o operador Case ou função IIF(), veja o exemplo:

    Create Table TabelaRemessa (Codigo Int Primary Key Identity(1,1), DataInicial DateTime Default GetDate(), DataFinal DateTime Null) Go Insert Into TabelaRemessa (DataInicial, DataFinal) Values (GetDate(), Null), (GetDate()+2, Null), (GetDate()+4, Null) Go

    -- Analisando se o valor da coluna DataFinal esta Null -- Select Codigo, DataInicial, Case When (DataFinal Is NULL) Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataFinal Is Null, DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go


    Ressalto que este é um exemplo de Código, um esboço, faça uma análise de qual abordagem poderia ser melhor, destaco que a função IIF() ela vai levar em consideração a condição aplicada a ela processando linha a linha, o que poderá atrapalhar a performance, como também, o Case, que em contra partida apresenta um comportamento mais aceitável depedendo do volume de dados.

    Neste outro trecho aqui, você vai poder justamente analisar a diferença entre as datas com base nos 30 minutos:

    -- Aplicando os trinta minutos após a passagem do tempo --

    Select Codigo, DataInicial, Case When (DataInicial < dateadd (minute, -30, GetDate()))

    >= 30) Then DateAdd(MINUTE,30,DataInicial) Else DataFinal End CaseDataFinal, IIF(DataInicial < dateadd (minute, -30, GetDate())

    DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal From TabelaRemessa Go



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]



    Obrigado pelo retorno.

    Não sei se fiz algo errado (não tenho muito conhecimento em SQL) mas não serviu exatamente para o que eu preciso.

    Preciso que o select só me traga as remessas que estão em processamento há mais de 30 minutos.

    Raphael,

    Ok, perfeito, alterei o código para análisar e apresentar somente as remessas com o tempo decorrido acima de 30 minutos, veja abaixo o outro exemplo:

    -- Analisando se o valor da coluna DataFinal esta Null, considerando acima de 30 minutos -- Select Codigo, DataInicial From TabelaRemessa Where DataFinal Is Null And DataInicial < dateadd (minute, -30, GetDate())
    Go

    -- Aplicando a soma de 30 minutos, através do comando Case ou função IIF() --
    Select Codigo,
               DataInicial,
               Case 
    		    When (DataInicial < dateadd (minute, -30, GetDate())) Then DateAdd(MINUTE,30,DataInicial)
    
    		   Else 
    		    DataFinal
    		   End CaseDataFinal,
    		   IIF(DataInicial < dateadd (minute, -30, GetDate()), DateAdd(MINUTE,30,DataInicial), DataFinal) As IIFDataFinal
    
    From TabelaRemessa
    Where DataFinal Is Null
    And DataInicial < dateadd (minute,-30, GetDate())
    Go


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]



    úterý 27. srpna 2019 13:12
    Moderátor
  • José, o primeiro código serviu perfeitamente. Como atualmente eu não tenho nenhuma remessa que caia nessa condição e o seu código não me trouxe nada, acredito que esteja correto. Os outros traziam alguma informação, dessa maneira já sabia que estava errado.

    Ok, Raphael.

    Observei que o Edvaldo acrescentou filtro pela coluna DataFim no código que ele postou. Me parece que a solução proposta por ele também funcionará.


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    úterý 27. srpna 2019 13:46
  • @José Diz

    Estive ausente do escritório por algum tempo e verifiquei hoje que a query não está me trazendo exatamente após 30 minutos. 

    Vou anexar um print para você ver melhor.

    Consegue me ajudar novamente?

    úterý 3. září 2019 20:45
  • Estive ausente do escritório por algum tempo e verifiquei hoje que a query não está me trazendo exatamente após 30 minutos. 

    Olá Raphael.

    Você pode transcrever para este tópico como está o código SQL em execução?


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    úterý 3. září 2019 21:48
  • Estive ausente do escritório por algum tempo e verifiquei hoje que a query não está me trazendo exatamente após 30 minutos. 

    Olá Raphael.

    Você pode transcrever para este tópico como está o código SQL em execução?


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    SELECT DataInicio, DiarioID, Fg_Status,    
           DATEDIFF (MINUTE, DataInicio, CURRENT_TIMESTAMP) [Processando há (minutos)]
    FROM TG_Gerenciador_FULL
    WHERE DataFim IS NULL
            AND DataInicio < DATEADD (MINUTE, -30, CURRENT_TIMESTAMP)
    AND Fg_Status = 0 OR Fg_Status = 1
    ORDER BY DataInicio DESC
    úterý 3. září 2019 22:01
  • SELECT DataInicio, DiarioID, Fg_Status,    
           DATEDIFF (MINUTE, DataInicio, CURRENT_TIMESTAMP) [Processando há (minutos)]
    FROM TG_Gerenciador_FULL
    WHERE DataFim IS NULL
            AND DataInicio < DATEADD (MINUTE, -30, CURRENT_TIMESTAMP)
    AND Fg_Status = 0 OR Fg_Status = 1
    ORDER BY DataInicio DESC

    Ok.

    A causa está aqui: "OR Fg_Status = 1". Basta que a coluna Fg_Status esteja 1 que será retornada linha, mesmo que não seja caso de processando há mais de 30 minutos.

    Sugiro que substitua por

           AND (Fg_Status = 0 OR Fg_Status = 1)

         


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    • Označen jako odpověď Raphael Lage úterý 3. září 2019 22:46
    • Upravený José Diz úterý 3. září 2019 23:17
    úterý 3. září 2019 22:09
  • SELECT DataInicio, DiarioID, Fg_Status,    
           DATEDIFF (MINUTE, DataInicio, CURRENT_TIMESTAMP) [Processando há (minutos)]
    FROM TG_Gerenciador_FULL
    WHERE DataFim IS NULL
            AND DataInicio < DATEADD (MINUTE, -30, CURRENT_TIMESTAMP)
    AND Fg_Status = 0 OR Fg_Status = 1
    ORDER BY DataInicio DESC

    Ok.

    A causa está aqui: "OR Fg_Status = 1". Basta que a coluna Fg_Status esteja 1 que será retornada linha, mesmo que não seja caso de processando há mais de 30 minutos.

    Sugiro que substitua por

           AND (Fg_Status = 0 OR Fg_Status = 1)

      


    José Diz     Belo Horizonte, MG - Brasil     [T-SQL performance tuning: Porto SQL]   [e-mail]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    Obrigado mais uma vez. Agora funcionou perfeitamente.
    úterý 3. září 2019 22:36