Encontre o número anterior na coluna que não está faltando em uma sequência
Tenho uma tabela com uma coluna que deve conter números em uma sequência completa; para simplificar, diremos de 101 a 110. No entanto, essa tabela depende de informações não confiáveis para serem inseridas manualmente, portanto, os números na sequência são perdidos. Há também uma coluna de data na mesma tabela que preciso consultar, mais sobre isso em instantes. Fui desafiado a encontrar todos os números de sequência ausentes junto com o número de sequência anterior que foi inserido, a data em que foi inserido e o próximo número de sequência com a data em que foi inserido. Encontrar os números de sequência que faltam é simples, é obter os registros anteriores e seguintes relevantes com os quais estou lutando. Então, se meus dados fossem assim;
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<html>
<body>
<table>
<tr>
<th>Seq No</th>
<th>Date Input</th>
</tr>
<tr>
<td>101</td>
<td>01-JAN-20</td>
</tr>
<tr>
<td>102</td>
<td>05-JAN-20</td>
</tr>
<tr>
<td>104</td>
<td>07-JAN-20</td>
</tr>
<tr>
<td>105</td>
<td>08-JAN-20</td>
</tr>
<tr>
<td>106</td>
<td>09-JAN-20</td>
</tr>
<tr>
<td>108</td>
<td>10-JAN-20</td>
</tr>
<tr>
<td>109</td>
<td>11-JAN-20</td>
</tr>
<tr>
<td>110</td>
<td>12-JAN-20</td>
</tr>
</table>
</body>
</html>
Meu conjunto de resultados seria semelhante a;
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<html>
<body>
<table>
<tr>
<th>Missing Seq No</th>
<th>Previous Date</th>
<th>Next Date</th>
<th>Notes</th>
</tr>
<tr>
<td>103</td>
<td>05-JAN-20</td>
<td>07-JAN-20</td>
<td>Dates from found seq nos 102 and 104</td>
</tr>
<tr>
<td>107</td>
<td>09-JAN-20</td>
<td>10-JAN-20</td>
<td>Dates from found seq nos 106 and 108</td>
</tr>
</table>
</body>
</html>
Mas sem a coluna de notas, ela está lá apenas para maior clareza.
Posso obter uma resposta, mas o sql é tão grande e pesado que é praticamente inútil. Obrigado.
Respostas
Se você quiser uma linha por lacuna, poderá usar as funções de janela:
select
lag_seq_no last_sequence_number,
lag_date_input last_date_input,
seq_no next_sequence_number,
date_input next_date_input
from (
select
t.*,
lag(seq_no) over(order by date_input) lag_seq_no,
lag(date_input) over(order by date_input) lag_date_input
from mytable t
) t
where seq_no > lag_seq_no + 1
Por outro lado, se você tem números consecutivos ausentes e deseja uma linha para cada um, precisa de algum tipo de recursão:
with
data(seq_no, date_input, lag_seq_no, lag_date_input) as (
select
t.*,
lag(seq_no) over(order by date_input) lag_seq_no,
lag(date_input) over(order by date_input) lag_date_input
from mytable t
),
cte (seq_no, date_input, lag_seq_no, lag_date_input) as (
select seq_no, date_input, lag_seq_no + 1, lag_date_input
from data
where seq_no > lag_seq_no + 1
union all
select seq_no, date_input, lag_seq_no + 1, lag_date_input
from cte
where seq_no > lag_seq_no + 1
)
select
lag_seq_no missing_seq_no,
lag_date_input last_date_input,
date_input next_date_input
from cte