2012-04-02 11 views
11

tengo algo de tabla como éstagrupo de valores que están en secuencia

row chequeNo 
1  15 
2  19 
3  20 
4  35 
5  16 

y que necesito para obtener el resultado como este

row from to  
1 15 16  
2 19 20  
3 35 35 

así que necesito grupos de chequeNo donde los valores serían secuenciales sin interrupciones chequeNo es una columna única. Además, debe hacerse con una consulta de selección sql, porque no tengo permisos para crear estructuras SQL, excepto para seleccionar consultas.

¿Entonces es posible?

agradecería cualquier ayuda

+7

Y la base de datos que está usar es? – Thilo

+4

O su ejemplo no tiene sentido o me falta algo –

+1

¿Está seguro de que el resultado deseado que escribió arriba es correcto? No veo ningún patrón en eso. –

Respuesta

2

Esto debería funcionar con Oracle 10 (sólo probado con Oracle 11)

select group_nr + 1, 
     min(chequeno) as start_value, 
     max(chequeno) as end_value 
from (
    select chequeno, 
     sum(group_change_flag) over (order by rn) as group_nr 
    from (
    select row_number() over (order by chequeno) as rn, 
      chequeno, 
      case 
      when chequeno - lag(chequeno,1,chequeno) over (order by chequeno) <= 1 then 0 
      else 1 
      end as group_change_flag 
    from foo 
) t1 
) t2 
group by group_nr 
order by group_nr 

(que debería funcionar con cualquier DBMS soportan funciones de ventanas SQL estándar, por ejemplo, PostgreSQL, DB2, SQL Server 2012)

21

Se puede utilizar la técnica de Aketi Jyuuzou llama Tabibitosan aquí:

SQL> create table mytable (id,chequeno) 
    2 as 
    3 select 1, 15 from dual union all 
    4 select 2, 19 from dual union all 
    5 select 3, 20 from dual union all 
    6 select 4, 35 from dual union all 
    7 select 5, 16 from dual 
    8/

Table created. 

SQL> with tabibitosan as 
    2 (select chequeno 
    3   , chequeno - row_number() over (order by chequeno) grp 
    4  from mytable 
    5 ) 
    6 select row_number() over (order by grp) "row" 
    7  , min(chequeno) "from" 
    8  , max(chequeno) "to" 
    9 from tabibitosan 
10 group by grp 
11/

     row  from   to 
---------- ---------- ---------- 
     1   15   16 
     2   19   20 
     3   35   35 

3 rows selected. 

Saludos,
Rob.

+0

Muy bueno. Mucho más elegante que mi solución. –

+2

+1 Gracias por dar el nombre de la técnica, esa pequeña información extra transforma "aquí está tu respuesta 1308044" a "aquí hay una técnica general que debes saber". –

+0

muchas gracias. He integrado esta solución a la consulta real y ahora funciona bien. – Harrison

0

Aquí es un enfoque "plain vanilla":

SELECT T1.chequeNo, T2.chequeNo 
FROM Table1 AS T1 INNER JOIN Table1 AS T2 ON T2.chequeNo >= T1.chequeNo 
WHERE 
NOT EXISTS (SELECT T0.chequeNo FROM Table1 T0 WHERE T0.chequeNo IN ((T1.chequeNo-1), (T2.chequeNo+1))) 
AND (SELECT COUNT(*) FROM Table1 T0 WHERE T0.chequeNo BETWEEN T1.chequeNo AND T2.chequeNo)=(T2.chequeNo - T1.chequeNo + 1) 
ORDER BY 1,2 

Por favor, hágamelo saber si es demasiado ineficiente para grandes conjuntos de datos.

0
CREATE TABLE YOUR_TABLE (
    chequeNo NUMBER PRIMARY KEY 
); 

INSERT INTO YOUR_TABLE VALUES (15); 
INSERT INTO YOUR_TABLE VALUES (19); 
INSERT INTO YOUR_TABLE VALUES (20); 
INSERT INTO YOUR_TABLE VALUES (35); 
INSERT INTO YOUR_TABLE VALUES (16); 

SELECT T1.chequeNo "from", T2.chequeNo "to" 
FROM 
    (
     SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN 
     FROM (
      SELECT chequeNo, LAG(chequeNo) OVER (ORDER BY chequeNo) PREV 
      FROM YOUR_TABLE 
     ) 
     WHERE PREV IS NULL OR chequeNo > PREV + 1 
    ) T1 
    JOIN 
    (
     SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN 
     FROM (
      SELECT chequeNo, LEAD(chequeNo) OVER (ORDER BY chequeNo) NEXT 
      FROM YOUR_TABLE 
     ) 
     WHERE NEXT IS NULL OR chequeNo < NEXT - 1 
    ) T2 
    USING (RN); 

Resultado:

from     to      
---------------------- ---------------------- 
15      16      
19      20      
35      35      

Si condimentar las cosas un poco ...

INSERT INTO YOUR_TABLE VALUES (17); 
INSERT INTO YOUR_TABLE VALUES (18); 

... obtenemos:

from     to      
---------------------- ---------------------- 
15      20      
35      35      
Cuestiones relacionadas