2010-08-27 26 views
6

Tengo una tabla que define gamas, por ejemplo:cómo Calc rangos en el oráculo

START | END | MAP 
1  | 10 | A 
11 | 15 | B 
... 

¿cómo puedo consulta en esa mesa por lo que el resultado será

ID | MAP 
1 | A 
2 | A 
3 | A 
4 | A 
5 | A 
6 | A 
7 | A 
8 | A 
9 | A 
10 | A 
11 | B 
12 | B 
13 | B 
14 | B 
15 | B 
... 

apuesto a que es un fácil ... Gracias por la ayuda

f.

+0

¿Pueden los datos (en la tabla de rangos) tener este aspecto? (Es decir, cuando C se extiende a otro rango.) START | END | MAPA 1 | 10 | A 11 | 15 | B 5 | 14 | C –

Respuesta

7
select * from Table, (Select Level as Id from dual connect by Level <= (Select Max(End)  from Table)) t 
Where t.Id between rr.Start and rr.End 
Order by Map, Start, Id 
+0

Tengo muchas buenas respuestas aquí, especialmente ese tipo con el gran artículo. ¡Pero este es simple, ordena y lo hizo! ¡Gracias amigo! f. – filippo

0
WITH r AS 
     (
     SELECT MAX(end - start) + 1 AS mr 
     FROM  ranges 
     ), 
     series AS 
     (
     SELECT level - 1 AS l 
     FROM  dual 
     CONNECT BY 
       level <= 
       (
       SELECT mr 
       FROM r 
       ) 
     ) 
SELECT start + l, map 
FROM ranges 
JOIN series 
ON  l <= end - start 

En PostgreSQL, usted podría hacer:

SELECT map, generate_series(start, end) 
FROM ranges 

Actualización:

Probado en los datos de la muestra:

WITH ranges AS 
     (
     SELECT 1 AS f_start, 10 AS f_end, 'A' AS map 
     FROM dual 
     UNION ALL 
     SELECT 11 AS f_start, 15 AS f_end, 'B' AS map 
     FROM dual 
     ), 
     r AS 
     (
     SELECT MAX(f_end - f_start) + 1 AS mr 
     FROM  ranges 
     ), 
     series AS 
     (
     SELECT level - 1 AS l 
     FROM  dual 
     CONNECT BY 
       level <= 
       (
       SELECT mr 
       FROM r 
       ) 
     ) 
SELECT f_start + l, map 
FROM ranges 
JOIN series 
ON  l <= f_end - f_start 
ORDER BY 
     2, 1 
+0

generate_series() es tan genial;) –

+0

esto realmente no funcionó ... solo devolvió mis un par de filas ... – filippo

+0

@flpgdt: ver la actualización de la publicación, funciona con los datos que ha proporcionado. – Quassnoi

0

Puedo darte una solución sucia. Pero por favor no te rías de mí :(

  1. Prepare una tabla ficticia, dicen DUMMY tabla que contiene un solo campo (DUMMY_ID), que sus valores son 1..n donde n es suficientemente grande como para su problema. Vamos tomar n = 100, por ejemplo,
  2. unirse a estas dos tablas, la tabla actual y la tabla ficticia igual que este:..

    SELECT DUMMY_ID, MAP dE DUMMY, (SELECT START, END, MAP DE ACTUAL) AS ACTUAL DONDE DUMMY_ID ENTRE START Y END

Tenga en cuenta que dado consulta anterior es MySQL. No usé Oracle por mucho tiempo, pero seguro que entendiste el punto.

2

Esta solución a primera vista parece complicada, pero generalmente resuelve cualquier rango. Resuelve el problema con VALUE que pueden interferir con cualquier otro rango.

En primer lugar crear tabla de ejemplo e insertar datos:

create table test_table (col_START NUMBER, col_END NUMBER, col_MAP CHAR(1)); 
insert into test_table(col_START, col_END, col_MAP) values(1,10,'A'); 
insert into test_table(col_START, col_END, col_MAP) values(11,15,'B'); 
insert into test_table(col_START, col_END, col_MAP) values(5,12,'C'); 

Ahora, los datos se ven así:

START | END | MAP 
1  | 10 | A 
11 | 15 | B 
5  | 12 | C 

Ahora crea tipo de objeto:

CREATE TYPE SampleType AS OBJECT 
(
    id number, 
    map_string varchar2(2000) 
) 
/

CREATE TYPE SampleTypeSet AS TABLE OF SampleType 
/

y también crear FUNCIÓN pipeline:

CREATE OR REPLACE FUNCTION GET_DATA RETURN SampleTypeSet 
PIPELINED 
IS 
    l_one_row SampleType := SampleType(NULL, NULL); 

BEGIN 

    FOR cur_data IN (select col_START, col_END, col_MAP from test_table) LOOP 
     FOR i IN cur_data.col_START..cur_data.col_END LOOP 
      l_one_row.id := i; 
      l_one_row.map_string := cur_data.col_MAP; 
      PIPE ROW(l_one_row); 
     END LOOP; 
    END LOOP; 

    RETURN; 
END GET_DATA; 
/

Finalmente, puede utilizar consulta sencilla:

SELECT * FROM TABLE(GET_DATA()); 

O crear y seleccionar de la vista (si desea ocultar implementación del objeto):

CREATE VIEW VIEW_ALL_DATA AS SELECT * FROM TABLE(GET_DATA()); 
SELECT * FROM VIEW_ALL_DATA; 

En base a esta mi artículo:

http://martin-mares.cz/2010/08/oracle-db-pipelined-function/