В моем приложении есть таблица users
таблица teams
таблица teams_users
и таблица assessments
. упрощенно:
**users**
id
**teams**
id
**teams_users**
team_id
user_id
**assessments**
id
user_id
team_id
Пользователь может иметь множество оценок.
Когда я захватываю пользователей в определенном контексте, я хочу также получить их связанные оценки (весь объект) плюс значение в качестве возвращаемого пользователя, team_ids
которые по существу являются результатом выщипывания столбца team_id
для всех строк в таблица teams_users
с пользователем user_id
.
Я знаю, как выполнять каждый из этих запросов отдельно, но я не уверен, насколько я могу объединиться в один эффективный запрос и даже еще не уверен, как это сделать, поскольку я довольно ржавый с SQL. Моя первая мысль была примерно такой:
SELECT users.id, users.name, users.email, users.role
FROM users
INNER JOIN assessments ON assessments.user_id = users.id
WHERE users.id='someID'
В этом вопросе, однако, я на самом деле ничего не делаю с оценками. Поэтому я рассматривал что-то вроде этого:
SELECT users.id, users.name, users.email, users.role, assessments
FROM users
INNER JOIN assessments ON assessments.user_id = users.id
WHERE users.id='someID'
Этот SORT работает, но возвращает оценки в виде массива значений с разделителями в круглых скобках (я использую JavaScript, а библиотека pg
противном случае анализирует ответы в JSON), что лучше исправлять на уровне SQL, чем анализировать в JSON:
{
id: 'mEPRVHp3',
name: 'Frank',
role: 'admin',
assessments: '(uibbH0ff,rPWZDIoA,mEPRVHp3,99,2017-12-01)'
}
Чтобы уточнить, я бы предпочел это так:
{
id: 'mEPRVHp3',
name: 'Frank',
role: 'admin',
assessments: [
{
id: 'uibbH0ff',
team_id: 'rPWZDIoA',
user_id: 'mEPRVHp3',
score: 99,
date: '2017-12-01'
}
]
}
Тогда отдельно, мне бы хотелось захватить teams_users
team_id
в том же запросе. Чтобы окончательный ответ был примерно таким:
{
id: 'mEPRVHp3',
name: 'Frank',
role: 'admin',
assessments: [
{
id: 'uibbH0ff',
team_id: 'rPWZDIoA',
user_id: 'mEPRVHp3',
score: 99,
date: '2017-12-01'
}
],
team_ids: ['rPWZDIoA']
}
Попробовал добавить teams_users.team_id AS team_ids
в конец инструкции SELECT, но это сломало весь запрос.
Опять же, не уверен, что это возможно, и в этом случае не ВСЕ уверенно, как это сделать.
Какие-нибудь мысли? Работа над моим ограниченным умением SQL.
Спасибо!
Предполагая, что вы используете PostgreSQL версии 9.3 или новее.
Я бы использовал row_to_json()
для "форматирования" записи оценки. Затем я буду использовать боковое соединение, чтобы получить идентификаторы вашей команды.
Вот так:
SELECT
usr.id,
usr.name,
usr.email,
usr.role,
row_to_json(asmnt) AS assessments, --Use row_to_json()
tusr.team_ids
FROM
users usr
INNER JOIN
assessments asmnt
ON asmnt.user_id = usr.id
INNER JOIN LATERAL
(
SELECT
array_agg(teams_users.team_id) AS team_ids
FROM
teams_users
WHERE
teams_users.user_id = usr.id
) tusr
ON TRUE
WHERE
usr.id = 'someID';
assessments
форматируются как один объект JSON (имеет смысл), но у пользователя может быть много оценок. Я попыталсяarray_to_json(asmnt)
но былаarray_to_json(asmnt)
ошибка, говорящая, что это не функция. Любые идеи, как это исправить? Спасибо!jsonb_build_array
работал как шарм! postgresql.org/docs/9.5/static/functions-json.html