使用连接查询 JSONB 字段
Querying JSONB fields with joins
我有一个包含两个 table 的数据库。一个包含事件,另一个包含这些事件的参与者。这些事件有一个 jsonb 字段,其中包含一个具有 "duration"
属性
的对象数组
事件
id
name
occurrences
1
"The Great Beyond"
[{"duration": 100}, {"duration": 200}, {"duration": 300}]
2
"The Final Countdown"
[{"duration": 50}]
3
"The Next Plain"
null
与会者
id
name
event_id
1
"Bob"
1
2
"Susan"
2
3
"Terry"
3
我想 运行 一个查询来提取有关这些事件的数据并展示事件的名称、有多少人参加以及每个事件的当前“持续时间”是多少(通过总结occurrences
列中的所有 duration
值。
我使用的当前查询导致与会者的 COUNT
值不正确。我怀疑这与我构建 JOIN
的方式有关,因此正在创建额外的行。
SELECT
events.id AS "ID",
events.name AS "Name",
SUM(coalesce(occurrences_arry->'duration', '0'):int) as "Duration",
COUNT(attendees.*) as "Attendees"
FROM
events
INNER JOIN attendees on attendees.event_id = events.id
LEFT JOIN jsonb_array_elements(events.occurrences) as occurrences_arry on true
GROUP BY events.id
我返回的结果对“与会者”的计数太高(最后一条记录应该有 1 名与会者,但说是 3 人)。我很确定它与我正在使用的 INNER JOIN
LEFT JOIN
组合有关,因此我可以利用 jsonb_array_elements
。每次添加新事件时,与会者人数都会增加
ID
Name
Duration
Attendees
2
"The Final Countdown"
50
1
3
"The Next Plain"
0
1
1
"The Great Beyond"
600
3
我如何才能最好地对我的与会者 table 执行 INNER JOIN
并总结每个活动的所有 duration
?
您可以在子查询中计算持续时间。您已经拥有大部分需要的代码,只需移动它,例如:
SELECT
events.id AS "ID",
events.name AS "Name",
(SELECT coalesce(SUM((occurrences_arry->>'duration')::int), 0)
FROM jsonb_array_elements(events.occurrences) as occurrences_arry) as "Duration",
COUNT(attendees.*) as "Attendees"
FROM
events
INNER JOIN attendees on attendees.event_id = events.id
GROUP BY events.id
A SUM
returns null,如果没有行,因此在这种情况下我使用 coalesce
默认为 0。
我有一个包含两个 table 的数据库。一个包含事件,另一个包含这些事件的参与者。这些事件有一个 jsonb 字段,其中包含一个具有 "duration"
属性
事件
id | name | occurrences |
---|---|---|
1 | "The Great Beyond" | [{"duration": 100}, {"duration": 200}, {"duration": 300}] |
2 | "The Final Countdown" | [{"duration": 50}] |
3 | "The Next Plain" | null |
与会者
id | name | event_id |
---|---|---|
1 | "Bob" | 1 |
2 | "Susan" | 2 |
3 | "Terry" | 3 |
我想 运行 一个查询来提取有关这些事件的数据并展示事件的名称、有多少人参加以及每个事件的当前“持续时间”是多少(通过总结occurrences
列中的所有 duration
值。
我使用的当前查询导致与会者的 COUNT
值不正确。我怀疑这与我构建 JOIN
的方式有关,因此正在创建额外的行。
SELECT
events.id AS "ID",
events.name AS "Name",
SUM(coalesce(occurrences_arry->'duration', '0'):int) as "Duration",
COUNT(attendees.*) as "Attendees"
FROM
events
INNER JOIN attendees on attendees.event_id = events.id
LEFT JOIN jsonb_array_elements(events.occurrences) as occurrences_arry on true
GROUP BY events.id
我返回的结果对“与会者”的计数太高(最后一条记录应该有 1 名与会者,但说是 3 人)。我很确定它与我正在使用的 INNER JOIN
LEFT JOIN
组合有关,因此我可以利用 jsonb_array_elements
。每次添加新事件时,与会者人数都会增加
ID | Name | Duration | Attendees |
---|---|---|---|
2 | "The Final Countdown" | 50 | 1 |
3 | "The Next Plain" | 0 | 1 |
1 | "The Great Beyond" | 600 | 3 |
我如何才能最好地对我的与会者 table 执行 INNER JOIN
并总结每个活动的所有 duration
?
您可以在子查询中计算持续时间。您已经拥有大部分需要的代码,只需移动它,例如:
SELECT
events.id AS "ID",
events.name AS "Name",
(SELECT coalesce(SUM((occurrences_arry->>'duration')::int), 0)
FROM jsonb_array_elements(events.occurrences) as occurrences_arry) as "Duration",
COUNT(attendees.*) as "Attendees"
FROM
events
INNER JOIN attendees on attendees.event_id = events.id
GROUP BY events.id
A SUM
returns null,如果没有行,因此在这种情况下我使用 coalesce
默认为 0。