sentencia rango por incluye fechas extremos ejemplos consulta clausula sql nhibernate set

sql - por - Encontrar rangos continuos en un conjunto de números



like en sql (4)

SQL no puede hacer esto en una sola consulta (excepto que hay mejoras de SQL nativo que desconozco), porque SQL no puede acceder a la fila ''antes'' o ''después''.

Necesitas pasar por la secuencia en un bucle.

Puede probar NHibernates Enumerable , que no carga las entidades en la memoria, sino que solo crea proxies de ellas. En realidad, no creo que sea una buena idea, ya que creará proxies para los 2 millones de números.

Plan B, usa paginación. A grandes rasgos, se ve así:

List<PhoneNumber> result = new List<PhoneNumber>(); int input = 1012; int pageSize = 100; int currentPage = 0; int expectedNumber = input; bool carryOn = true; while(carryOn) { var numbers = session .CreateQuery("from PhoneNumber pn where pn.Number > :input") .SetInt("input", input) .SetFirstResult(currentPage * pageSize) .SetMaxResult(pageSize) .List<PhoneNumbers>(); foreach(var number in numbers) { expectNumber++; if (number.Number != expectedNumber) { carryOn = false; break; } result.Add(number); } currentPage++; }

Y lo mismo para el rango anterior en la otra dirección.

Tengo un conjunto razonablemente grande de números de teléfono (aproximadamente 2 millones) en una tabla de base de datos. Estos números se han insertado en bloques, por lo que hay muchos rangos continuos de números, desde 10 hasta 10 mil en un rango. Algunos de estos números están en uso y, por lo tanto, están marcados como no disponibles, el resto están disponibles. Dado un número en particular, necesito una forma de encontrar rangos continuos de números, tanto por encima como por debajo de ese número. El rango debe continuar hasta que encuentre un número no disponible o encuentre el límite de dos rangos.

Por ejemplo, dado el siguiente conjunto:

1000 1001 1002 1010 1011 1012 1013 1020 1021 1022

Hacer una búsqueda usando 1012 como parámetro debería devolver 1010, 1011, 1012, 1013.

¿Cuál es una buena forma de formar una consulta para encontrar estos rangos? Usamos NHibernate en la parte superior del servidor SQL, una solución con cualquiera de ellas está bien.


Si usa SQL server, debería poder hacer una consulta recursiva que se unirá en root.number = leaf.number + 1

Si selecciona el número desde la raíz y desde la última recursión, y el nivel de la recursión, debe tener una consulta activa.

Primero probaría el rendimiento de eso, y luego, si no es satisfactorio, cambiaré al enfoque basado en cursor / fila (que en este caso haría un trabajo con un único escaneo completo, donde la recursión puede fallar al alcanzar la profundidad máxima de recursión).

De lo contrario, sus opciones son almacenar datos de manera diferente y mantener una lista de números mínimos y máximos asociados con una tabla.

Esto podría implementarse realmente en desencadenantes que no tengan una penalización tan alta en las actualizaciones de fila única (las actualizaciones en la fila única de la tabla base actualizarían, borrarían o dividirían una fila en la tabla min-max; esto se puede determinar consultando el fila ''anterior'' y ''siguiente'' solamente).


Teóricamente, los elementos de un conjunto no tienen un valor particular, así que supongo que también tiene una columna de ID continua que define el orden de los números. Algo como esto:

ID Number 1 1000 2 1001 3 1002 4 1010 5 1011 6 1012 7 1013 8 1020 9 1021 10 1022

Puede crear una columna adicional que contenga el resultado del Number - ID :

ID Number Diff 1 1000 999 2 1001 999 3 1002 999 4 1010 1006 5 1011 1006 6 1012 1006 7 1013 1006 8 1020 1012 9 1021 1012 10 1022 1012

Los números en el mismo rango tendrán el mismo resultado en la columna Diff.


Use una tabla auxiliar de todos los valores secuenciales posibles o materialice una en un CTE, por ej.

WITH -- materialize a table of sequential integers l0 AS (SELECT 0 AS c UNION ALL SELECT 0), l1 AS (SELECT 0 AS c FROM l0 AS a, l0 AS b), l2 AS (SELECT 0 AS c FROM l1 AS a, l1 AS b), l3 AS (SELECT 0 AS c FROM l2 AS a, l2 AS b), l4 AS (SELECT 0 AS c FROM l2 AS a, l3 AS b), l5 AS (SELECT 0 AS c FROM l2 AS a, l4 AS b), nums AS (SELECT row_number() OVER(ORDER BY c) AS n FROM l5), -- materialize sample table MyTable (ID) AS ( SELECT 1000 UNION ALL SELECT 1001 UNION ALL SELECT 1002 UNION ALL SELECT 1010 UNION ALL SELECT 1011 UNION ALL SELECT 1012 UNION ALL SELECT 1013 UNION ALL SELECT 1020 UNION ALL SELECT 1021 UNION ALL SELECT 1022 ), -- materialize parameter table params (param) AS (SELECT 1012) SELECT MIN(N1.n) - 1 AS last_in_sequence FROM nums AS N1 CROSS JOIN params AS P1 WHERE N1.n > P1.param AND NOT EXISTS ( SELECT * FROM MyTable AS T1 WHERE N1.n = T1.ID );