SQL/ORACLE Filtrar registros ativos no mês

Tenho uma tabela que grava meus registros onde uma coluna grava a data_inicial e outra coluna a data_final. Preciso gerar um relatório onde o usuário pesquisa todos os registros que estavam entre o o período de por exemplo 01/03/2017 a 31/03/2017.

O que eu precisava é pegar os registros que mesmo tendo iniciado antes desse período ocuparam dias no meu mês 03. Se eu uso por exemplo data_inicial between 01/03/2017 and 31/03/2017, os meus registros que tinham data inicial 27/02/2017 e data final 01/04/2017 nao aparecem. Alguem tem uma sugestão de como eu poderia fazer isso?

Neste caso, você precisa pensar nas seguintes possibilidades:

  • Registros com data inicial igual ou posterior à data inicial informada e data final igual ou anterior à data final informada

    WHERE data_inicial >= TO_DATE(‘01/03/2017’, ‘dd/mm/yyyy’) AND data_final <= TO_DATE(‘31/03/2017’, ‘dd/mm/yyyy’)

  • Registros com data inicial igual ou posterior à data inicial informada e data final posterior à data final informada

data_inicial >= TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final >= TO_DATE('31/03/2017', 'dd/mm/yyyy')

  • Registros com data inicial anterior à data inicial informada e data final igual ou anterior à data final informada

data_inicial < TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final <= TO_DATE('31/03/2017', 'dd/mm/yyyy')

  • Registros com data inicial anterior à data inicial informada e data final posterior à data final informada

data_inicial < TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final > TO_DATE('31/03/2017', 'dd/mm/yyyy')

SELECT col1, col2, col3, col4, coln
FROM tabela_que_grava_meus_registros
WHERE (data_inicial >= TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final <= TO_DATE('31/03/2017', 'dd/mm/yyyy'))
OR (data_inicial >= TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final >= TO_DATE('31/03/2017', 'dd/mm/yyyy'))
OR (data_inicial < TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final <= TO_DATE('31/03/2017', 'dd/mm/yyyy'))
OR (data_inicial < TO_DATE('01/03/2017', 'dd/mm/yyyy') AND data_final > TO_DATE('31/03/2017', 'dd/mm/yyyy'));

O principal risco disso é, caso não exista outros critérios de filtro, você sempre terá todos os registros retornados.

Esses 4 casos resumem-se num:

  • registos com data inicial antes da data de fim informado e com data final após a data de inicio informada.

    SELECT col1, col2, col3, col4, coln
    FROM tabela_que_grava_meus_registros
    WHERE data_final >= TO_DATE(‘01/03/2017’, ‘dd/mm/yyyy’)
    AND data_inicial <= TO_DATE(‘31/03/2017’, ‘dd/mm/yyyy’)

Em relação à questão inicial, queres contabilizar os dados entre

  • o máximo da data de inicio do registo e a data de inicio do mes
  • e o mínimo da data de fim do registo e a data de fim do mês

Traduzindo para SQL (não sei qual o teu SGBD, podem ser necessárias pequenas alterações):

SELECT datediff(least(data_final, TO_DATE('31/03/2017', 'dd/mm/yyyy')), greatest(data_inicial, TO_DATE('01/03/2017', 'dd/mm/yyyy') ))
  FROM tabela_que_grava_meus_registros
 WHERE data_final >= TO_DATE('01/03/2017', 'dd/mm/yyyy') 
   AND data_inicial <= TO_DATE('31/03/2017', 'dd/mm/yyyy')