我有一个定义范围的表格,例如:
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
...
我打赌它很简单...感谢您的帮助
F。
答案 0 :(得分: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
答案 1 :(得分:2)
这个解决方案乍一看看起来很复杂,但通常可以解决任何范围。解决可能会受到任何其他范围干扰的VALUE问题。
首先创建样本表并插入数据:
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-db-pipelined-function/
答案 2 :(得分: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
在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
答案 3 :(得分:0)
我可以给你一个肮脏的解决方案。但请不要嘲笑我:(
加入这两个表,您的实际表和DUMMY表。就像这样:
选择
DUMMY_ID
,
MAP
从
DUMMY
,
(SELECT START
,END
,MAP
FROM ACTUAL
)AS ACTUAL
哪里
在DUMMY_ID
和START
END
{。}}
醇>
请注意,上面给出的查询是MySQL。我没有长时间使用Oracle,但确定你明白了。