【问题标题】:Oracle - Convert value from rows into rangesOracle - 将行中的值转换为范围
【发布时间】:2010-09-02 16:51:51
【问题描述】:

是否有任何技术可以允许这样的行集

WITH 
base AS
(
    SELECT  1 N FROM DUAL UNION ALL
    SELECT  2 N FROM DUAL UNION ALL
    SELECT  3 N FROM DUAL UNION ALL

    SELECT  6 N FROM DUAL UNION ALL
    SELECT  7 N FROM DUAL UNION ALL

    SELECT 17 N FROM DUAL UNION ALL
    SELECT 18 N FROM DUAL UNION ALL
    SELECT 19 N FROM DUAL UNION ALL

    SELECT 21 N FROM DUAL
)
SELECT  a.N
FROM base a

产生结果

 1     3
 6     7
17    19
21    21

实际上是从行到范围的操作。 我在 Oracle Land 玩游戏,如果有任何建议,我将不胜感激。

【问题讨论】:

  • 你是如何定义你的范围的?如果它们是 3x-1
  • @mark 1-3 是一个组,没有适用的特定公式。

标签: sql oracle range


【解决方案1】:

我觉得这可能可以改进,但它有效:

WITH base AS  (
    SELECT  1 N FROM DUAL UNION ALL
    SELECT  2 N FROM DUAL UNION ALL
    SELECT  3 N FROM DUAL UNION ALL
    SELECT  6 N FROM DUAL UNION ALL
    SELECT  7 N FROM DUAL UNION ALL
    SELECT 17 N FROM DUAL UNION ALL
    SELECT 18 N FROM DUAL UNION ALL
    SELECT 19 N FROM DUAL UNION ALL
    SELECT 21 N FROM DUAL
)
, lagged AS
(
    SELECT n, LAG(n) OVER (ORDER BY n) lag_n FROM base
)
, groups AS
(
    SELECT n, row_number() OVER (ORDER BY n) groupnum
      FROM lagged
      WHERE lag_n IS NULL OR lag_n < n-1
)
, grouped AS
(
    SELECT n, (SELECT MAX(groupnum) FROM groups
                 WHERE groups.n <= base.n
              ) groupnum
      FROM base
)
SELECT groupnum, MIN(n), MAX(n)
  FROM grouped
  GROUP BY groupnum
  ORDER BY groupnum

【讨论】:

  • 是的,这就是工作。我今天学了些新东西。谢谢戴夫。
【解决方案2】:

另一种方式:

WITH base AS  
(
    SELECT  1 N FROM DUAL UNION ALL
    SELECT  2 N FROM DUAL UNION ALL
    SELECT  3 N FROM DUAL UNION ALL
    SELECT  6 N FROM DUAL UNION ALL
    SELECT  7 N FROM DUAL UNION ALL
    SELECT 17 N FROM DUAL UNION ALL
    SELECT 18 N FROM DUAL UNION ALL
    SELECT 19 N FROM DUAL UNION ALL
    SELECT 21 N FROM DUAL
)
select min(n), max(n) from 
  (
    select n, connect_by_root n root from base
    connect by prior n = n-1
    start with n not in (select n from base b 
                         where exists (select 1 from base b1 where b1.n = b.n-1)
                        )
  ) 
  group by root
  order by root

【讨论】:

    【解决方案3】:

    另一种方式:

    with base as (
        select  1 n from dual union all
        select  2 n from dual union all
        select  3 n from dual union all
        select  6 n from dual union all
        select  7 n from dual union all
        select 17 n from dual union all
        select 18 n from dual union all
        select 19 n from dual union all
        select 21 n from dual)
    select a,b 
    from (select a
                ,case when b is not null and a is not null
                      then b
                      else lead(n) over (order by n)
                end b
          from (select n
                      ,a
                      ,b
                from (select n
                            ,case n-1 when lag (n) over (order by n) then null else n end a
                            ,case n+1 when lead (n) over (order by n) then null else n end b
                      from base)
          where a is not null
             or b is not null))
    where a is not null
    order by a
    

    【讨论】:

      猜你喜欢
      • 2022-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 1970-01-01
      • 2011-11-14
      • 1970-01-01
      • 2019-07-27
      相关资源
      最近更新 更多