为较大的选择查询的每一行选择一个表或数组

时间:2010-12-22 12:48:56

标签: sql oracle oracle11g

使用Oracle 11g

假设我们有两个表:

CREATE TABLE items (
    item_id NUMBER(22,0)
);

CREATE TABLE messages (
    item_id NUMBER(22,0),
    message_code NUMBER(22,0)
);

其中有一个(项目)到多个(消息)关系。我想在单个查询中选择所有内容以将其转换为java。有可能写出这样的查询,它会给我输出如:

ID         MESSAGE
----------------------------------
1          (100, 105, 201)
2          (100, 105)

其中MESSAGE列是一个数组或类似的东西(不是连接的字符串)?

3 个答案:

答案 0 :(得分:7)

您可以使用字段级游标:

WITH    items AS
        (
        SELECT  1 AS item_id
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id
        FROM    dual
        ),
        messages AS
        (
        SELECT  1 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 105 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 201 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 15 AS message_code
        FROM    dual
        )
SELECT  item_id,
        CURSOR
        (
        SELECT  message_code
        FROM    messages m
        WHERE   m.item_id = i.item_id
        )
FROM    items i

或创建表格类型并将值MULTISET转换为该类型:

CREATE TYPE t_message_code AS TABLE OF INTEGER

WITH    items AS
        (
        SELECT  1 AS item_id
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id
        FROM    dual
        ),
        messages AS
        (
        SELECT  1 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 105 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 201 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 15 AS message_code
        FROM    dual
        )
SELECT  item_id,
        CAST
        (
        MULTISET
        (
        SELECT  message_code
        FROM    messages m
        WHERE   m.item_id = i.item_id
        ) AS t_message_code
        )
FROM    items i

答案 1 :(得分:1)

在Quassnoi的答案的基础上,还有COLLECT函数在另一个答案中与MULTISET做同样的事情但没有子查询。

CREATE TYPE t_message_code AS TABLE OF INTEGER;

WITH    items AS
        (
        SELECT  1 AS item_id
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id
        FROM    dual
        ),
        messages AS
        (
        SELECT  1 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 105 AS message_code
        FROM    dual
        UNION ALL
        SELECT  1 AS item_id, 201 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 100 AS message_code
        FROM    dual
        UNION ALL
        SELECT  2 AS item_id, 15 AS message_code
        FROM    dual
        )
SELECT  i.item_id, 
  cast(collect(m.message_code) as t_message_code) as messages_codes
FROM    
  items i
  join messages m on (m.item_id = i.item_id)
group by i.item_id;

答案 2 :(得分:0)

注意:这会给你一个字符串(不是你想要的),但我会在这里留下这个答案,因为这个问题经常被问到,并不是所有人都知道这个简单的解决方案< / p>

  SELECT item_id AS id,
         wm_concat(message_code) AS message
    FROM messages
GROUP BY item_id

如果您需要围绕邮件ID列表使用括号,则可以使用连接:

'(' || wm_concat(message_code) || ')' AS message