You can use the following query:
SELECT
CAST(dh.data->'message'->>'id' AS INTEGER) AS message_id,
ml.message_text
FROM
disruption_history dh
JOIN message_library ml
ON ml.component_code IN
(SELECT
CAST(jsonb_array_elements_text(
dh.data->'message'->'preRecordedMessageList'->'preRecordedMessageCodes'
)
AS INTEGER)
) ;
Note that I have used an explicit join (avoid the implicit ones!).
The trick here is to convert your preRecordedMessageCodes into a set of texts, by using the jsonb_array_elements_text function, that are further CAST to integer, and then compared to the ml.component_code (by using an IN condition):
You can check the whole setup at dbfiddle here
Note also that this structure produces an awful execution plan, that requires whole sequential scans of both tables. I have not been able to find any kind of index that helps the queries.
Note that this won't work if you have arrays with NULLs in them, which I assume wouldn't make sense.
Keeping order:
If you want to keep the elements of the array in order, you need to use a WITH ORDINALITY predicate to obtain not only the array element, but also its relative position, and use it to ORDER BY
-- Keeping order
SELECT
CAST(dh.data->'message'->>'id' AS INTEGER) AS message_id,
ml.message_text
FROM
disruption_history dh
JOIN LATERAL
jsonb_array_elements_text(dh.data->'message'->'preRecordedMessageList'->'preRecordedMessageCodes')
WITH ORDINALITY AS x(mc, ord) /* We will want to use 'ord' to order by */
ON true
JOIN message_library ml ON ml.component_code = cast(mc AS INTEGER)
ORDER BY
message_id, ord ;
Watch this at dbfiddle here
Alternative:
If the structure of your json data is always the same, I would strongly recommend that you normalize your design (at least partially):
CREATE TABLE disruption_history_no_json
(
disruption_history_id SERIAL PRIMARY KEY,
message_id INTEGER,
pre_recorded_message_codes INTEGER[]
) ;
CREATE INDEX idx_disruption_history_no_json_pre_recorded_message_codes
ON disruption_history_no_json USING GIN (pre_recorded_message_codes) ;
Would allow for a much simpler and efficient and simpler query:
SELECT
message_id,
ml.message_text
FROM
disruption_history_no_json dh
JOIN message_library ml
ON ml.component_code = ANY(pre_recorded_message_codes) ;
Check everything together at dbfiddle here
JSON(B) allows you not to normalize, and not to have to think much about your table structures, but you pay a steep price in performance and maintainability.