[英]SQL View - Creating a array of JSON objects for one-to-many relationships
我正在嘗試創建一個名為“Inpatients”的 SQL 視圖來簡化我的數據庫查詢,這對於我數據庫中的關鍵一對一數據效果很好,但我現在正在努力適應我的一對多。 我在 Rails 上使用 Ruby 和 Scenic gem 和 PostgreSQL 數據庫(但希望將來能夠容納 SQL 服務器)。
具體來說,我有一個可以執行多項任務的患者列表。 我已經設法將任務鏈接起來並將它們放入 JSON object 但我為每個患者獲得了多行(等於任務數)。
這就是我目前按列構建的方式:
jsonb_build_object(
'id', Tasks.id, 'title', Tasks.title, 'completed', Tasks.completed
) as tasks
如何將這些任務聚合到 json 對象(所有任務)的數組中,而不是多行,每行都有一個 JSON object 用於單個任務?
我在 Stack Overflow 和其他地方嘗試了其他地方的各種命令,但無法弄清楚我做錯了什么( GROUP_BY
, json_agg
. array_to_json
,嵌套 SQL Select 語句)。 理想情況下,我會有一個不可知的解決方案(我目前正在使用 Postgres,但想支持 SQL 服務器)。
任何幫助將不勝感激!
屏幕截圖- 當我顯示結果時,這顯示了 output,其中最后一列是我希望作為 json 對象的單個數組的任務。 詳細信息是隨機生成的,並不代表真實的患者。
SQL 查看- 這是我創建的完整 SQL 語句
SELECT
Encounters.id as encounter_id,
Encounters.start, Encounters.end, Encounters.estimated_end,
Patients.id as patient_id,
Patients.healthid, Patients.localid, Patients.governmentid, Patients.hexeid,
Patients.given_names, Patients.last_name, Patients.gender, Patients.admin_gender,
Patients.birth_date, Patients.birth_time, Patients.deceased,
Beds.id as bed_id,
Beds.number, Beds.bay, Beds.cubicle, Beds.level, Beds.clean,
Locations.id as location_id,
Locations.title,
jsonb_build_object(
'id', Tasks.id, 'title', Tasks.title, 'completed', Tasks.completed
) as tasks
FROM Encounters
INNER JOIN Patients ON Encounters.patient_id=Patients.id
INNER JOIN Beds ON Encounters.bed_id=Beds.id
INNER JOIN Locations ON Beds.location_id=Locations.id
INNER JOIN Tasks ON Patients.id=Tasks.patient_id
WHERE Encounters.end IS null
要為每個患者在數組中聚合Tasks
json 對象,您可以使用這樣的 CTE
WITH patient_tasks AS (
SELECT
patients.id,
json_agg(
jsonb_build_object(
'id', Tasks.id,
'title', Tasks.title,
'completed', Tasks.completed)
) AS tasks
FROM patients
JOIN Tasks ON Patients.id=Tasks.patient_id
GROUP BY patients.id
)
SELECT
Encounters.id as encounter_id,
Encounters.start, Encounters.end, Encounters.estimated_end,
Patients.id as patient_id,
Patients.healthid, Patients.localid, Patients.governmentid, Patients.hexeid,
Patients.given_names, Patients.last_name, Patients.gender, Patients.admin_gender,
Patients.birth_date, Patients.birth_time, Patients.deceased,
Beds.id as bed_id,
Beds.number, Beds.bay, Beds.cubicle, Beds.level, Beds.clean,
Locations.id as location_id,
Locations.title,
patient_tasks.tasks
FROM Encounters
INNER JOIN Patients ON Encounters.patient_id = Patients.id
INNER JOIN Beds ON Encounters.bed_id = Beds.id
INNER JOIN Locations ON Beds.location_id = Locations.id
INNER JOIN patient_tasks ON patient_tasks.id = Encounters.patient_id
WHERE Encounters.end IS null
您可以在派生表中聚合任務:
SELECT encounters.id AS encounter_id,
encounters.start, encounters.end, encounters.estimated_end,
patients.id as patient_id,
patients.healthid, patients.localid, patients.governmentid, patients.hexeid,
patients.given_names, patients.last_name, patients.gender, patients.admin_gender,
patients.birth_date, patients.birth_time, patients.deceased,
beds.id as bed_id,
beds.number, beds.bay, beds.cubicle, beds.level, beds.clean,
locations.id as location_id,
locations.title,
tsk.all_tasks
FROM encounters
JOIN patients ON encounters.patient_id = patients.id
JOIN beds ON encounters.bed_id = beds.id
JOIN locations ON beds.location_id = locations.id
JOIN (
select tk.patient_id
jsonb_agg(to_jsonb(tk)) as all_tasks
from tasks tk
group by tk.patient_id
) tsk ON patients.id = tsk.patient_id
WHERE encounters.end IS null
to_jsonb(tk)
會將tasks
表中的完整行轉換為 JSON 值。 如果您只想選擇幾列,請使用jsonb_build_object
,就像您已經做的那樣: (jsonb_agg(jsonb_build_object(...))
如果您只想排除一或兩列,使用-
可能更容易,例如to_jsonb(tk) - 'created_at' - 'modified_at'
從生成的 JSON 中刪除created_at
和modified_at
鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.