2

表から:

|   name   |   range   |
------------------------
| 'Range1' | '456-458' |
| 'Range2' |   '11-13' |

この結果を得ようとしているだけです:

|   name   |   range   | value |
--------------------------------
| 'Range1' | '456-458' |  456  |
| 'Range1' | '456-458' |  457  |
| 'Range1' | '456-458' |  458  |
| 'Range2' |   '11-13' |   11  |
| 'Range2' |   '11-13' |   12  |
| 'Range2' |   '11-13' |   13  |

ソーステーブルに範囲が1つしかない場合に正常に機能するクエリを作成しました。

WITH data AS (
    SELECT 'Range1' name, '456-458' range FROM dual
)
SELECT ROWNUM, name, range, LEVEL value
FROM data, dual
WHERE LEVEL >= to_number(SUBSTR(range, 1, INSTR(range,'-')-1))
CONNECT BY LEVEL <= to_number(SUBSTR(range, INSTR(range,'-')+1));

ただし、2 つの範囲を取る場合は、数万行を返します。

WITH data AS (
    SELECT 'Range1' name, '456-458' range FROM dual
    UNION
    SELECT 'Range2' name, '11-13' range FROM dual
)
SELECT ROWNUM, name, range, LEVEL value FROM data, dual
WHERE LEVEL >= to_number(SUBSTR(range, 1, INSTR(range,'-')-1))
CONNECT BY LEVEL <= to_number(SUBSTR(range, INSTR(range,'-')+1));

このクエリを改善して必要なものを取得することは可能ですか、それとも私のアプローチが最初は間違っていますか?

Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
4

2 に答える 2

2

11g では、このタイプのものに対して再帰的な因数分解されたサブクエリを使用できます。

SQL> with data as (select name, range,
  2                       to_number(substr(range, 1, instr(range,'-')-1)) from_val,
  3                       to_number(substr(range, instr(range,'-')+1)) to_val
  4                  from your_table),
  5  ranges (name, range, curr_val, from_val, to_val)
  6  as (select name, range, from_val, from_val, to_val
  7        from data
  8      union all
  9      select name, range, curr_val+1, from_val, to_val
 10        from ranges
 11       where curr_val < to_val)
 12  select name, range, curr_val
 13    from ranges
 14   order by name, curr_val;

NAME   RANGE     CURR_VAL
------ ------- ----------
Range1 456-458        456
Range1 456-458        457
Range1 456-458        458
Range2 11-13           11
Range2 11-13           12
Range2 11-13           13
于 2013-02-17T15:42:26.543 に答える
1

再帰(DazzaLの答え)はより良い解決策ですが、階層クエリを使用してそれを行う方法を見たい場合。

WITH data AS (
SELECT 'Range1' name
     , '456-460' range 
  FROM dual
UNION ALL
SELECT 'Range2' name
     , '11-13' range 
  FROM dual)

, ranges AS (
SELECT name
     , range
     , to_number(SUBSTR(range, 1, INSTR(range,'-')-1)) from_range
     , to_number(SUBSTR(range, INSTR(range,'-')+1)) to_range
  FROM data

), max_seq AS (
SELECT MAX(to_range - from_range) + 1 max_seq
  FROM ranges

), seq AS (
SELECT ROWNUM seq
  FROM max_seq
CONNECT BY LEVEL <= max_seq
) 

SELECT ROWNUM
     , name
     , range
     , from_range + seq - 1 value
  FROM ranges
 INNER JOIN seq
    ON seq <=  (to_range - from_range) + 1
于 2013-02-17T17:01:30.850 に答える