Comprobando secuencia con consulta SQL
-
03-07-2019 - |
Pregunta
Tengo una tabla de pedidos que mantiene todos los pedidos de todas nuestras tiendas. Escribí una consulta para verificar las órdenes de secuencia para cada tienda. Se parece a eso.
select WebStoreID, min(webordernumber), max(webordernumber), count(webordernumber)
from orders
where ordertype = 'WEB'
group by WebStoreID
Puedo verificar que todas las órdenes están presentes con esta consulta. El número de pedido web es el número de 1 ... n.
¿Cómo puedo escribir una consulta para encontrar pedidos faltantes sin unirme a una tabla temporal / diferente?
Solución
Puedes unirte a la tabla en sí misma para detectar filas que no tienen una fila anterior:
select cur.*
from orders cur
left join orders prev
on cur.webordernumber = prev.webordernumber + 1
and cur.webstoreid = prev.webstoreid
where cur.webordernumber <> 1
and prev.webordernumer is null
Esto detectaría huecos en la secuencia 1 ... n, pero no detectaría duplicados.
Otros consejos
Haría una tabla auxiliar de " todos los enteros de 1 a n " (consulte http://www.sql-server-helper.com/ functions / integer-table.aspx para algunas formas de hacerlo con una función de SQL Server, pero como es algo que necesitarás una y otra vez, lo convertiré en una tabla real de todos modos, y con cualquier motor SQL es fácil de hacer eso, solo una vez) luego use una consulta anidada, SELECCIONE el valor DE los enteros CUANDO el valor NO ESTÁ (SELECCIONE el número web DE las órdenes)
& amp; c. También vea http://www.sqlmag.com/Article/ArticleID/99797/ sql_server_99797.html para un problema similar al suyo, " detectando huecos en una secuencia de números " ;.
Si tiene la función rank () pero no la función lag () (en otras palabras, SQL Server), puede usar esto (sugerido por http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-programming / 10594 / Return-gaps-in-a-sequence ):
create table test_gaps_in_sequence (x int)
insert into test_gaps_in_sequence values ( 1 )
insert into test_gaps_in_sequence values ( 2 )
insert into test_gaps_in_sequence values ( 4 )
insert into test_gaps_in_sequence values ( 5 )
insert into test_gaps_in_sequence values ( 8 )
insert into test_gaps_in_sequence values ( 9 )
insert into test_gaps_in_sequence values ( 12)
insert into test_gaps_in_sequence values ( 13)
insert into test_gaps_in_sequence values ( 14)
insert into test_gaps_in_sequence values ( 29)
...
select lower_bound
, upper_bound
from (select upper_bound
, rank () over (order by upper_bound) - 1 as upper_rank
from (SELECT x+n as upper_bound
from test_gaps_in_sequence
, (SELECT 0 n
UNION
SELECT -1
) T
GROUP BY x+n
HAVING MAX(n) = -1
) upper_1
) upper_2
, (select lower_bound
, rank () over (order by lower_bound) as lower_rank
from (SELECT x+n as lower_bound
from test_gaps_in_sequence
, (SELECT 0 n
UNION
SELECT 1
) T
GROUP BY x+n
HAVING MIN(n) = 1
) lower_1
) lower_2
where upper_2.upper_rank = lower_2.lower_rank
order by lower_bound
... o, para incluir los " límites externos " ;:
select lower_bound
, upper_bound
from (select upper_bound
, rank () over (order by upper_bound) - 1 as upper_rank
from (SELECT x+n as upper_bound
from test_gaps_in_sequence
, (SELECT 0 n
UNION
SELECT -1
) T
GROUP BY x+n
HAVING MAX(n) = -1
) upper_1
) upper_2
full join (select lower_bound
, rank () over (order by lower_bound) as lower_rank
from (SELECT x+n as lower_bound
from test_gaps_in_sequence
, (SELECT 0 n
UNION
SELECT 1
) T
GROUP BY x+n
HAVING MIN(n) = 1
) lower_1
) lower_2
on upper_2.upper_rank = lower_2.lower_rank
order by coalesce (lower_bound, upper_bound)
Si su base de datos admite funciones analíticas, podría utilizar una consulta similar a la siguiente:
select prev+1, curr-1 from
( select webordernumber curr,
coalesce (lag(webordernumber) over (order by webordernumber), 0) prev
from orders
)
where prev != curr-1;
La salida mostrará las brechas, por ejemplo,
prev+1 curr-1
------ ------
3 7
significaría que faltan los números 3 a 7 inclusive.