【问题标题】:Efficient query to join three tables连接三个表的高效查询
【发布时间】:2018-05-16 02:41:03
【问题描述】:

我的应用有一个users 表、一个teams 表、一个teams_users 表和一个assessments 表。过于简单:

**users**
id

**teams**
id

**teams_users**
team_id
user_id

**assessments**
id
user_id
team_id

一个用户可以有许多评估。

当我在特定上下文中抓取用户时,我也想抓取他们的相关评估(整个对象),另外,作为返回用户的值,team_ids 这基本上是采摘@ 的结果teams_users 表中所有行的 987654327@ 列以及用户的 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'

这种类型的作品,但将评估作为括号分隔的值数组返回(我使用的是 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_usersteam_ids。所以最终响应是这样的:

{
    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 技能。

谢谢!

【问题讨论】:

    标签: javascript sql json postgresql pg


    【解决方案1】:

    假设您使用的是 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';
    

    【讨论】:

    • 这太棒了!非常感谢!遇到一个问题——assessments 被格式化为单个 JSON 对象(有意义),但用户可以进行许多评估。我尝试了array_to_json(asmnt),但抛出了一个错误,说这不是一个函数。任何想法如何解决这一问题?谢谢!
    • 知道了! jsonb_build_array 工作就像一个魅力! postgresql.org/docs/9.5/static/functions-json.html
    猜你喜欢
    • 2019-01-26
    • 2012-05-02
    • 2015-09-23
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多