Reputation: 11802
Using Oracle 11g
Suppose we have two tables:
CREATE TABLE items (
item_id NUMBER(22,0)
);
CREATE TABLE messages (
item_id NUMBER(22,0),
message_code NUMBER(22,0)
);
where there is one (item) to many (messages) relationship. I want to select all the stuff in a single query to get it into java. Is is possible to write such a query, that it would give me output like:
ID MESSAGE
----------------------------------
1 (100, 105, 201)
2 (100, 105)
where MESSAGE column is an array or something like that (not a concatenated string)?
Upvotes: 3
Views: 727
Reputation: 2895
To build on Quassnoi's answer, there is also the COLLECT
function which will do the same thing as MULTISET
in the other answer but without the subquery.
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;
Upvotes: 1
Reputation: 254906
NOTE: this will give you a string (not you wanted), but I'll left this answer here since this question is asked quite often and not all people yet know about such simple solution
SELECT item_id AS id,
wm_concat(message_code) AS message
FROM messages
GROUP BY item_id
If you need parentheses around the message ids list you could use concatenation:
'(' || wm_concat(message_code) || ')' AS message
Upvotes: 0
Reputation: 425321
You can use field-level cursors:
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
or create a table type and cast a MULTISET
of the values to that type:
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
Upvotes: 8