Я сделал DB-Fiddle этой проблемы, чтобы его было легче читать: https://www.db-fiddle.com/f/iwGtTkgBpAtsohFuAG2A4L/2
С учетом следующей схемы:
-- Table that holds the data of a Character.
CREATE TABLE Character (
id SERIAL,
name TEXT,
description TEXT,
PRIMARY KEY (id)
);
-- 1:M relationship between Character -> CharacterSkill, one Character can have multiple skills.
CREATE TABLE CharacterSkill (
id SERIAL,
character INTEGER,
name TEXT,
description TEXT,
value_1 INTEGER,
PRIMARY KEY (id),
FOREIGN KEY (character) REFERENCES Character (id)
);
-- 1:M relationship between CharacterSkill -> CharacterSkillItems. One skill might require one or more items to level up.
CREATE TABLE CharacterSkillItems (
id SERIAL,
skill_id INTEGER,
item_id INTEGER, --references to another table that is going to be joined for the item name. For sake of length I don't add it.
amount INTEGER,
PRIMARY KEY (id),
FOREIGN KEY (skill_id) REFERENCES CharacterSkill (id)
--FOREIGN KEY (item_id) REFERENCES Item (id)
);
С следующие тестовые данные:
-- Adding a character to the database.
INSERT INTO Character (name, description) VALUES ('Character 1', 'Character 1 Description');
-- Adding the skills of that character. They have two.
INSERT INTO CharacterSkill (character, name, description, value_1) VALUES (1, 'Character 1 Skill 1', 'Character 1 Skill 1 Description', 5);
INSERT INTO CharacterSkill (character, name, description, value_1) VALUES (1, 'Character 1 Skill 2', 'Character 1 Skill 2 Description', 50);
-- First skill requires 2 items to level up.
INSERT INTO CharacterSkillItems (skill_id, item_id, amount) VALUES (1, 10, 5);
INSERT INTO CharacterSkillItems (skill_id, item_id, amount) VALUES (1, 10, 5);
-- Second skill requires 3 items to level up.
INSERT INTO CharacterSkillItems (skill_id, item_id, amount) VALUES (2, 10, 10);
INSERT INTO CharacterSkillItems (skill_id, item_id, amount) VALUES (2, 20, 5);
INSERT INTO CharacterSkillItems (skill_id, item_id, amount) VALUES (2, 40, 5);
Каков наилучший подход к извлечению данных персонажа со всеми его навыками и необходимыми предметами (для этого потребуется еще одно СОЕДИНЕНИЕ для имен предметов) * Только 1013 * для представления данных? Один из подходов, который я могу придумать, состоит в том, чтобы разделить это на несколько запросов, но из того, что я исследовал, можно ли справиться с этим в одном запросе, лучше оставить его в одном запросе, поэтому, если бы мне пришлось оставить его только в одном запросе Я думал об использовании json_agg с json_build_object, но это, кажется, становится неприятным, так как я продолжаю углубляться в плане вложенных запросов и при работе с несколькими навыками / предметами.
РЕДАКТИРОВАТЬ: Я обновил базу данных -Поддержать мою попытку построить его, используя json методы. Это работает, но, как я уже упоминал ранее, чем глубже я продолжаю работать с JOINs, тем хуже это выглядит. Я не уверен, есть ли лучший способ справиться с этим.
Запрос в вопросе:
SELECT
char.name,
char.description,
skills.skill_list
FROM
Character char
JOIN (
SELECT
skill.character,
json_agg(
json_build_object(
'name', skill.name, 'description',
skill.description, 'value_1', skill.value_1,
'costs', cost_list.costs
)
) AS "skill_list"
FROM
CharacterSkill skill
JOIN (
SELECT
skill_id,
json_agg(
json_build_object(
'item_id', item_id, 'amount', amount
)
) AS "costs"
FROM
SkillUpgradeItem
GROUP BY
skill_id
) cost_list ON skill.id = cost_list.skill_id
GROUP BY
character
) skills ON skills.character = char.id;