簡體   English   中英

SQL 視圖 - 為一對多關系創建 JSON 對象數組

[英]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_BYjson_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_atmodified_at鍵。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM