【问题标题】:How to unfold the results of an Oracle query based on the value of a column如何根据列的值展开 Oracle 查询的结果
【发布时间】:2015-09-11 11:44:15
【问题描述】:

我在 Oracle DB 上有一个包含两列的表。我希望看到每一行重复的次数与第二列中存储的数字一样多。表格如下所示:

col1 col2  
a    2  
b    3  
c    1

我想写一个返回这个的查询:

col1 col2
a    2  
a    2   
b    3    
b    3    
b    3    
c    1

所以 col2 的值决定了一行重复的次数。有没有简单的方法来实现这一点?

谢谢!

【问题讨论】:

    标签: sql oracle split


    【解决方案1】:

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE test ( col1, col2 ) AS
              SELECT 'a', 2 FROM DUAL
    UNION ALL SELECT 'b', 3 FROM DUAL
    UNION ALL SELECT 'c', 1 FROM DUAL
    

    查询 1

    SELECT col1,
           col2
    FROM   test t,
           TABLE(
             CAST( 
               MULTISET(
                 SELECT LEVEL
                 FROM   DUAL
                 CONNECT BY LEVEL <= t.col2
               )
               AS SYS.ODCINUMBERLIST
             )
           )
    

    Results

    | COL1 | COL2 |
    |------|------|
    |    a |    2 |
    |    a |    2 |
    |    b |    3 |
    |    b |    3 |
    |    b |    3 |
    |    c |    1 |
    

    【讨论】:

      【解决方案2】:

      如果 a 是你的桌子,那么你也可以这样做:

      select a1.col1 , a1.col2 
            from a a1
            join  (select level col2  from dual 
            connect by level < ( select max(col2) + 1 from a))   a2
            on a2.col2 between 1 and a1.col2
      

      【讨论】:

        【解决方案3】:
        with src (col1, col2) as (
            SELECT 'a', 2 FROM DUAL UNION ALL
            SELECT 'b', 3 FROM DUAL UNION ALL
            SELECT 'c', 1 FROM DUAL
        )
        SELECT
            src.*
        FROM
            src
            JOIN (
                SELECT LEVEL val FROM DUAL
                CONNECT BY LEVEL <= (SELECT MAX(col2) FROM src)
            ) gen ON gen.val <= src.COL2
        ORDER BY
            src.col1
        

        或者在Oracle 12中可以使用

        with src (col1, col2) as (
            SELECT 'a', 2 FROM DUAL UNION ALL
            SELECT 'b', 3 FROM DUAL UNION ALL
            SELECT 'c', 1 FROM DUAL
        )
        SELECT
            src.*
        FROM
            src
            CROSS APPLY (SELECT NULL FROM DUAL CONNECT BY LEVEL <= src.col2)
        ORDER BY
            col1;
        

        【讨论】:

        • 如果:col2 中的值大于src 表中的行数,则您的第一个查询不起作用;如果数字有差距;或者如果有重复的数字。 (前两种情况会返回太少的行,而在第三种情况下会返回太多行)
        【解决方案4】:

        假设 col1 是唯一的,这里有一个替代方法(我添加了一个额外的列只是为了显示其他列可以存在):

        with src (col1, col2, col3) as (
            SELECT 'a', 'b', 2 FROM DUAL UNION ALL
            SELECT 'b', 'c', 3 FROM DUAL UNION ALL
            SELECT 'c', 'd', 1 FROM DUAL
        )
        select col1, col2, col3
        from   src
        connect by level <= col3
                   and prior col1 = col1
                   and prior sys_guid() is not null;
        
        COL1 COL2       COL3
        ---- ---- ----------
        a    b             2
        a    b             2
        b    c             3
        b    c             3
        b    c             3
        c    d             1
        

        【讨论】:

        • PRIOR DBMS_RANDOM.VALUE IS NOT NULL 将在 99.9999999% 的时间内工作 - 但是它有可能会两次返回相同的值,然后你会得到 ORA-01436: CONNECT BY loop in user data (你会很难尝试复制错误)。 PRIOR SYS_GUID() IS NOT NULL 不会受此影响。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-25
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多