как рассчитать диапазоны в оракуле - PullRequest
6 голосов
/ 27 августа 2010

У меня есть таблица определения диапазонов, например ::1001

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

как мне запросить эту таблицу, чтобы результат был

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
...

Бьюсь об заклад, это легко ... Спасибо за помощь

е.

Ответы [ 4 ]

7 голосов
/ 27 августа 2010
 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
2 голосов
/ 27 августа 2010

Это решение на первый взгляд выглядит сложным, но обычно разрешает любой диапазон.Решите проблему со значениями, которые могут помешать любому другому диапазону.

Сначала создайте пример таблицы и вставьте данные:

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');

Теперь данные выглядят так:

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

Теперь создайте тип объекта:

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

CREATE TYPE SampleTypeSet AS TABLE OF SampleType
/

А также создайте ТРУБОПРОВОДНУЮ ФУНКЦИЮ:

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;
/

Наконец, вы можете использовать простой запрос:

SELECT * FROM TABLE(GET_DATA());

Или создать и выбратьэто из поля зрения (если вы хотите скрыть реализацию OBJECT):

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

На основании этой моей статьи:

http://martin -mares.cz / 2010/08 / oracle-дб-конвейерный-функция /

0 голосов
/ 27 августа 2010

Я могу дать вам грязное решение. Но, пожалуйста, не смейтесь надо мной: (* ​​1001 *

  1. Подготовьте фиктивную таблицу, скажем таблицу DUMMY, которая содержит только одно поле (DUMMY_ID), значения которого равны 1..n, где n достаточно велико для вашей проблемы. Для примера возьмем n = 100.
  2. Соедините эти две таблицы, вашу фактическую таблицу и таблицу DUMMY. Просто так:

    ВЫБРАТЬ DUMMY_ID, MAP ОТ DUMMY, (ВЫБРАТЬ START, END, MAP ОТ ACTUAL) КАК ACTUAL ГДЕ DUMMY_ID МЕЖДУ START И END

Обратите внимание, что приведенным выше запросом является MySQL. Я долгое время не пользовался Oracle, но уверен, что вы поняли.

0 голосов
/ 27 августа 2010
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

В PostgreSQL вы можете просто сделать:

SELECT  map, generate_series(start, end)
FROM    ranges

Обновление:

Проверено на данных образца:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...