Por favor, considere este script:
Declare @tbl Table
(
F1 int,
F2 int,
Year int,
Month tinyint
)
Insert into @tbl
values
(10, 1, 2020, 1),
(10, 1, 2020, 2),
(10, 1, 2020, 3),
(10, 1, 2020, 4),
(10, 2, 2020, 5),
(10, 1, 2020, 6),
(10, 1, 2020, 7),
(11, 1, 2020, 1),
(11, 1, 2020, 2),
(11, 2, 2020, 3),
(11, 2, 2020, 4),
(11, 1, 2020, 5),
(12, 1, 2020, 1),
(12, 1, 2020, 2),
(12, 1, 2020, 3),
(12, 1, 2020, 4)
Eu escrevi esta consulta:
Select
F1, F2, year, month,
Row_number() over (partition by F1, F2 order by year, month) as rownumber,
Rank() over (partition by F1, F2 order by year, month) as rnk
From
@tbl
Order by
f1, f2, year, month
Esta consulta retorna este conjunto de resultados:
F1 | F2 | Ano | Mês | Número da linha | RNK-R |
---|---|---|---|---|---|
10 | 1 | 2020 | 1 | 1 | 1 |
10 | 1 | 2020 | 2 | 2 | 2 |
10 | 1 | 2020 | 3 | 3 | 3 |
10 | 1 | 2020 | 4 | 4 | 4 |
10 | 1 | 2020 | 6 | 5 | 5 |
10 | 1 | 2020 | 7 | 6 | 6 |
10 | 2 | 2020 | 5 | 1 | 1 |
11 | 1 | 2020 | 1 | 1 | 1 |
11 | 1 | 2020 | 2 | 2 | 2 |
11 | 1 | 2020 | 5 | 3 | 3 |
11 | 2 | 2020 | 3 | 1 | 1 |
11 | 2 | 2020 | 4 | 2 | 2 |
12 | 1 | 2020 | 1 | 1 | 1 |
12 | 1 | 2020 | 2 | 2 | 2 |
12 | 1 | 2020 | 3 | 3 | 3 |
Mas eu quero esse resultado:
F1 | F2 | Ano | Mês | Sequência |
---|---|---|---|---|
10 | 1 | 2020 | 1 | 1 |
10 | 1 | 2020 | 2 | 2 |
10 | 1 | 2020 | 3 | 3 |
10 | 1 | 2020 | 4 | 4 |
10 | 2 | 2020 | 5 | 1 |
10 | 1 | 2020 | 6 | 1 |
10 | 1 | 2020 | 7 | 2 |
11 | 1 | 2020 | 1 | 1 |
11 | 1 | 2020 | 2 | 2 |
11 | 2 | 2020 | 3 | 1 |
11 | 2 | 2020 | 4 | 2 |
11 | 1 | 2020 | 5 | 1 |
12 | 1 | 2020 | 1 | 1 |
12 | 1 | 2020 | 2 | 2 |
12 | 1 | 2020 | 3 | 3 |
12 | 1 | 2020 | 4 | 4 |
Ou seja, em cada conjunto do mesmo valor F1,
sequenciar por ano e depois por mês,
mas redefinir o número de sequência ano-mês a cada alteração F2 .
Como posso atingir o resultado desejado? Obrigado
Isso é basicamente um problema de lacunas e ilhas disfarçado. Aqui, cada "ilha" é um grupo de registros pertencentes ao mesmo
F1
bloco onde oF2
valor não mudou em sequência ao longo do ano e do mês. Podemos gerar um pseudogrupo para manter o controle desses registros e, em seguida, usar oROW_NUMBER()
para gerar os valores de sequência final. Observe que esse valor de pseudogrupo é redefinido para 1 quando oF1
bloco termina ou osF2
valores mudam.Demonstração
Depois de determinar as bordas (momentos nas sequências agrupadas em F1 onde F2 muda), você pode subtrair a posição da última borda de todas as posições subsequentes:
Aqui ele roda em um SQLFiddle .
Como você vai querer o máximo de uma posição com janela,
você precisará de pelo menos uma passagem para cada função de janela,
portanto, será necessário o uso de um CTE.
Observe que usei uma definição de janela para evitar repetir seu uso (e assim evitar erros de cópia).
Usamos a
LAG()
função para olhar o valor F2 da linha anterior (dentro do mesmo grupo F1, ordenado por Ano e Mês). Se o valor F2 for diferente da linha anterior, significa que um novo grupo está começando. Nesse caso, marcamos com 1 (chamadoIsNewGroup
). Se for o mesmo, marcamos com 0.Pegamos a
IsNewGroup
coluna e calculamos um total corrente usandoSUM()
. Esse total corrente (chamadoGroupID
) nos ajuda a atribuir um número exclusivo a cada grupo de linhas que compartilham o mesmo valor F2 dentro de um grupo F1. Para cada grupo (com base em F1 e GroupID), geramos um número de sequência usandoROW_NUMBER()
. Essa sequência é ordenada por Ano e Mês. Por fim, classificamos tudo por F1, Ano e Mês para que os resultados apareçam na ordem correta.