【问题标题】:How can I return multiple identical rows based on a quantity field in the row itself?如何根据行本身的数量字段返回多个相同的行?
【发布时间】:2011-04-09 13:23:33
【问题描述】:

我正在使用 oracle 从购物应用程序中输出订单项。每个项目都有一个数量字段,可能大于 1,如果是,我想返回该行 N 次。

这就是我所说的桌子

product_id, quanity
1, 3,
2, 5

我正在寻找一个会返回的查询

1,3
1,3
1,3
2,5
2,5
2,5
2,5
2,5

这可能吗?我看到this 对 SQL Server 2005 的回答,我正在寻找几乎与 oracle 完全相同的东西。不幸的是,建立一个专门的数字表不是一种选择。

【问题讨论】:

    标签: oracle select repeat rownum


    【解决方案1】:

    首先创建示例数据:

    create table my_table (product_id number , quantity number);
    insert into my_table(product_id, quantity) values(1,3);
    insert into my_table(product_id, quantity) values(2,5);
    

    现在运行这个 SQL:

      SELECT product_id, quantity
        FROM my_table tproducts
            ,(    SELECT LEVEL AS lvl
                    FROM dual
              CONNECT BY LEVEL <=  (SELECT MAX(quantity) FROM my_table)) tbl_sub
       WHERE tbl_sub.lvl BETWEEN 1 AND tproducts.quantity
    ORDER BY product_id, lvl;
    
    PRODUCT_ID   QUANTITY
    ---------- ----------
             1          3
             1          3
             1          3
             2          5
             2          5
             2          5
             2          5
             2          5
    

    这个问题可能与此相同:how to calc ranges in oracle

    更新解决方案,适用于 Oracle 9i

    你可以像这样使用 pipelined_function():

    CREATE TYPE SampleType AS OBJECT
    (
      product_id number,
      quantity 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 product_id, quantity FROM my_table ORDER BY product_id) LOOP
            FOR i IN 1..cur_data.quantity LOOP
                l_one_row.product_id := cur_data.product_id;
                l_one_row.quantity := cur_data.quantity;
                PIPE ROW(l_one_row);
            END LOOP;
        END LOOP;
    
        RETURN;
    END GET_DATA;
    /
    

    现在你可以这样做了:

    SELECT * FROM TABLE(GET_DATA());
    

    或者这个:

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

    两者的结果相同。

    (根据我的文章pipelined function

    【讨论】:

    • 你用11g吗?我永远无法在 9i 的 connect by level 子句中运行子查询。
    • 你是对的,在 Oracle 9i 上引发错误:ORA-01473。我会为 Oracle 9i 写一个更好的解决方案...等一下,我会更新我的“答案”:)
    • 感谢您的详尽回复。我最终对我的最高级别进行了硬编码,因为我正在处理的表非常庞大,并且在数量字段上没有索引,所以当我像这样测试它时它已经倒下。但是,如果您对该数量字段进行了索引,则这是一种更灵活的计算方式。
    【解决方案2】:

    我在示例中使用了 15 作为最大值,但您应该将其设置为 9999 或任何您将支持的最大数量。

    create table t (product_id number, quantity number);
    insert into t values (1,3);
    insert into t values (2,5);
    
    select t.* 
      from t 
        join (select rownum rn from dual connect by level < 15) a 
                                     on a.rn <= t.quantity
    order by 1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-02
      • 1970-01-01
      • 2014-09-12
      相关资源
      最近更新 更多