A tabela em que estou trabalhando tem três componentes:
- Uma
ID
coluna (chave primária em outra tabela) - Algumas colunas de dados
- Data válida
from
/to
colunas.
Valores:
ID Data From To
1 a 2015-01-01 2015-01-05
1 a 2015-01-06 2015-01-10
1 b 2015-01-11 2015-01-15
1 a 2015-01-16 2015-01-20
2 c 2015-01-01 2015-01-05
2 c 2015-01-06 2015-01-10
A tabela é atualizada tirando "instantâneos" de outra fonte de dados em alguns intervalos e atribuindo datas de validade aos registros. O problema é que esses instantâneos criam entradas duplicadas para registros (com datas de validade diferentes) que não foram alteradas durante esse intervalo.
Quero reduzir o tamanho da tabela procurando linhas com datas consecutivas, mesclando-as e atribuindo-lhes um único período de validade. Por exemplo:
ID Data From To
1 a 2015-01-01 2015-01-10
1 b 2015-01-11 2015-01-15
1 a 2015-01-16 2015-01-20
2 c 2015-01-01 2015-01-10
A lógica que tenho atualmente é:
- Selecione e classifique todas as linhas por ID, campos de dados e campos 'válidos de' (para que estejam em grupos de linhas consecutivas).
- Use um cursor para comparar linhas adjacentes quanto à similaridade.
- Se forem iguais, mescle as linhas e altere o período de validade para incluir as duas linhas.
Entendo que os cursores são muito ineficientes (tenho um grande conjunto de dados), por isso estou procurando outras abordagens.
CREATE TABLE
declaração na pergunta.Respostas:
Se esta for apenas uma tabela de intervalos consecutivos, o seu caso poderá ser tratado como um problema clássico de "lacunas e ilhas", no qual você só precisa isolar ilhas de intervalos consecutivos e depois "condensá-las" usando o mínimo
[from]
e o máximo[to]
por ilha.Existe um método estabelecido para resolver isso usando duas chamadas ROW_NUMBER:
Esta consulta funcionará na versão mais baixa que o SQL Server 2005.
fonte
Consegui escrever uma consulta para resolver esse problema. Ele usa várias junções e um loop while para mesclar registros. Este código é compatível com o SQL Server 2008 R2.
fonte
Apenas no caso de você ter períodos não contíguos que, apesar de consecutivos, devem permanecer separados, eu vim com esta solução:
Veja no SQL Fiddle
fonte
Eu escrevi uma consulta que parece funcionar. Ele usa expressões de tabela comuns, instruções MERGE e funções analíticas. No entanto, é compatível apenas com o SQL server 2012+. Você pode encontrar a essência aqui: MergeRecordsByValidityDate.sql
fonte