Из таблицы в PostgreSQL 10 я пытаюсь соединить все элементы массива в нескольких дочерних элементах одного и того же поля jsonb
с их родительской строкой, что-то вроде этого вопроса или этого . Но я делаю ошибку в JOIN
, так что вместо того, чтобы получать отдельные элементы массива, я заключаю отдельные элементы массива в один элемент массива.
Вот сокращенное определение таблицы:
CREATE TABLE public.worker_customformstore (
id integer NOT NULL DEFAULT nextval('worker_customformstore_id_seq'::regclass),
created_on timestamp with time zone NOT NULL,
store jsonb,
schema_id integer NOT NULL,
polymorphic_ctype_id integer,
pdf_key character varying(100) COLLATE pg_catalog."default" NOT NULL,
last_updated timestamp with time zone
)
и пример значения для поля store
:
'{"Subcontractor Use": {
"labor": [
{
"note": null,
"hours": {
"dt": null,
"ot": null,
"st": 1,
"pdt": null,
"pot": null
},
"employee": {
"id": 456,
"trade": "XXX",
"is_active": true,
"last_name": "Uknow",
"first_name": "Noone",
"company_supplied_id": "456"
},
"external subcontractor": false
},
{
"note": null,
"hours": {
"dt": null,
"ot": null,
"st": 8,
"pdt": null,
"pot": null
},
"employee": {
"id": 123,
"trade": "",
"member": null,
"is_active": true,
"last_name": "Guy",
"user_role": "WORKER",
"first_name": "Some",
"company_supplied_id": "123"
},
"external subcontractor": false
}
],
"Equipment": [
{
"note": null,
"hours": {
"idle": null,
"over": null,
"running": 8
},
"quantity": 1,
"equipment": {
"id": 6243,
"status": "Rented",
"project": "8399",
"category": "XXXXX",
"caltrans_id": "00-20",
"description": "19",
"equipment_id": "Scissor",
"idle_time_price": 0,
"over_time_price": 0,
"running_time_price": 0
}
}
]
}
}'
Мой упрощенный запрос выглядит так:
SELECT
cufstore.id,
CASE
WHEN labor IS NOT DISTINCT FROM NULL THEN
0
WHEN (jsonb_array_elements(labor) -> 'hours' ->> 'st') = '' THEN
0
ELSE
COALESCE((jsonb_array_elements(labor) -> 'hours' ->> 'st')::numeric, 0)
END
-- more stuff here ...
as total_hours,
CASE
WHEN labor IS NOT DISTINCT FROM NULL THEN
0
ELSE
COALESCE(jsonb_array_length(cufstore.store -> 'Subcontractor Use' -> 'labor'), 0)
END as total_workers,
labor, equipment
FROM public.worker_customformstore AS cufstore
...
LEFT OUTER JOIN LATERAL
(SELECT
jsonb_array_elements(jsonb_strip_nulls(cufstore.store -> 'Subcontractor Use' -> 'labor'))
WHERE cufstore.store -> 'Subcontractor Use' ->> 'labor' IS NOT NULL
) labor on true
LEFT OUTER JOIN LATERAL
(SELECT
jsonb_array_elements(jsonb_strip_nulls(cufstore.store -> 'Subcontractor Use' -> 'Equipment'))
WHERE cufstore.store -> 'Subcontractor Use' ->> 'Equipment' IS NOT NULL
) equipment on true
В дополнение к множеству избыточных вызовов jsonb_array_elements
, они не позволяют мне рефакторизовать повторяющуюся логику в функцию, потому что я получаю сообщение об ошибке, касающейся функций, возвращающих множество в COALESCE
в определении функции (хотя нет претензий, когда это происходит в теле моего запроса).
Я думаю, что я хочу что-то вроде:
LEFT OUTER JOIN LATERAL
jsonb_array_elements(jsonb_strip_nulls(cufstore.store -> 'Subcontractor Use' -> 'labor')) labor
ON jsonb_typeof(labor) = 'array'
Но при попытке получить это cannot extract elements from a scalar
, когда данные NULL
или выглядят неправильно.
Возможно, я в корне неправильно понимаю, что я могу сделать, но вот как выглядит столбец equipment
:
("{""hours"": {""running"": 8}, ""quantity"": 1, . . .}")
и я бы хотел иметь возможность спросить о equipment -> 'hours' ->> 'running'
без необходимости оборачивать его в jsonb_array_elements(equipment)
. Нужно ли это делать или я случайно добавляю скобки в начале и конце значения столбца?