【发布时间】:2016-10-09 13:29:44
【问题描述】:
我有以下表格:
CREATE TABLE sequence (
id serial PRIMARY KEY
-- ...other sequence data
)
CREATE TABLE sound (
id serial PRIMARY KEY
-- ...other sound data
)
CREATE TABLE layer (
id serial PRIMARY KEY,
index smallint NOT NULL,
sequence integer NOT NULL REFERENCES sequence (id)
)
CREATE TABLE layerSound (
id serial PRIMARY KEY,
index smallint NOT NULL,
layer integer NOT NULL REFERENCES layer (id),
sound integer NOT NULL REFERENCES sound (id)
)
所以我有序列。每个序列都有很多层。每一层 有很多layerSounds。每个 layerSound 都附有一个声音。
我想写一个可以选择某个序列的查询(返回JSON) 通过它的 ID,然后也加入:
- 此序列使用的层数组
- layerSounds 的聚合数组,按层分组
- 此序列使用的一组独特声音(跨所有 layerSounds)
例如:
{
sequence: 3,
layers: [1, 2],
layerSounds: [
{ layer: 1, sounds: [1, 2] },
{ layer: 2, sounds: [2, 3] }
],
sounds: [
{ id: 1, foo: "bar" },
{ id: 2, foo: "baz" },
{ id: 3, foo: "blah" }
]
}
所以目标是只将不同的声音数据完整地写出一次,然后是 layerSounds.sounds 数组只有声音 ID。所以声音数据不会重复。
到目前为止,我的方法是选择序列,然后分别聚合其他表。我按序列 ID 对每个进行分组,然后针对外部查询加入一次。
虽然这可行,但我注意到我必须在每个 JOIN 查询中重复连接,以便始终按 sequenceId 分组。
所以要按 sequenceId 对 layerSounds 进行分组,我将 layer 与 layerSound 连接起来以发出声音。然后我再次执行完全相同的连接来计算该序列使用的所有声音。我已包含以下查询。
我的问题是,有没有办法改进这个查询?这种方法有问题吗?或者像这样重用连接是正常的吗?
感谢您的宝贵时间。
查询:
SELECT
sequence.id,
layers.ids AS layers,
layerSounds.ids AS layerSounds,
sounds.ids AS sounds
FROM sequence
JOIN (
SELECT
sequence,
json_agg(id) AS ids
FROM layer
GROUP BY sequence
) layers ON layers.sequence = sequence.id
JOIN (
SELECT
sequence,
json_agg(layerSounds) AS ids
FROM layer
JOIN (
SELECT
layerSound.layer,
json_agg(sound.id) AS ids
FROM layerSound
JOIN sound
ON sound.id = layerSound.sound
GROUP BY layerSound.layer
) layerSounds ON layerSounds.layer = layer.id
GROUP BY sequence
) layerSounds ON layerSounds.sequence = sequence.id
JOIN (
SELECT
sequence,
json_agg(DISTINCT sound.id) AS ids
FROM layer
JOIN layerSound
ON layerSound.layer = layer.id
JOIN sound
ON sound.id = layerSound.sound
GROUP BY sequence
) sounds ON sounds.sequence = sequence.id
【问题讨论】:
标签: sql postgresql