高效查询以加入三个表

时间:2017-12-01 23:07:46

标签: javascript sql json postgresql pg

我的应用有一个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

我知道如何分别执行这些查询,但我不确定我可以将多少内容组合成一个有效的查询,更不确定如何这样做,因为我和#39;我对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技能。

谢谢!

1 个答案:

答案 0 :(得分:2)

假设您使用的是PostgreSQL 9.3或更高版本。

我会使用row_to_json()来"格式"评估记录。然后我会使用横向连接来获得你的团队ID。

像这样:

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';