【问题标题】:pgsql DELETE + LIMIT + JOIN + ORDERpgsql DELETE + LIMIT + JOIN + ORDER
【发布时间】:2021-04-18 14:26:42
【问题描述】:

我正在使用 PostgreSQL,并且我有一个游戏供玩家参加。

我有下表来描述玩家和锦标赛玩家(参加给定锦标赛的玩家)。这些表被简化为仅包含查询中使用的内容:

CREATE TABLE player (
    id INTEGER NOT NULL,
    username VARCHAR(255),
    push_notification_token VARCHAR(255)
);

CREATE TABLE tournament_player (
    tournament_id INTEGER NOT NULL,
    player_id INTEGER NOT NULL,
    victories INTEGER NOT NULL
);

当锦标赛结束时,我想以 100 人为一组删除所有锦标赛玩家,然后我还希望按照他们在锦标赛中的排名(胜利 DESC)进行排序。

我目前正在使用以下查询来删除、限制和加入:

DELETE FROM tournament_player tp 
    USING player p
    WHERE tp.player_id = p.id 
        AND (tp.tournament_id, tp.player_id) IN (
            SELECT tournament_id, player_id 
            FROM tournament_player
        LIMIT 100)
RETURNING tp.player_id, tp.victories, 
    p.username, p.push_notification_token;

我有两个问题:

  • 我如何也通过锦标赛玩家(胜利)订购 (DESC)
  • 这个查询是浪费资源还是优化得足够好? (我的意思不是在字段中添加 INDEX)

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    您可以在limit 之前的内部查询中添加order by tp.victories desc,以获得您想要的结果。

    DELETE FROM tournament_player tp 
        USING player p
        WHERE tp.player_id = p.id 
            AND (tp.tournament_id, tp.player_id) IN (
                SELECT tournament_id, player_id 
                FROM tournament_player
                order by tp.victories desc
            LIMIT 100)
    RETURNING tp.player_id, tp.victories, 
        p.username, p.push_notification_token;
    

    您也可以使用exits 代替IN,如下所示:

    DELETE FROM tournament_player tp 
        USING player p
        WHERE tp.player_id = p.id 
            AND exists
            (
                SELECT 1 
                FROM tournament_player tpr
                where tpr.tournament_id=tp.tournament_id and tpr.player_id=tp.player_id
                order by tp.victories desc
                LIMIT 100
            )
        RETURNING tp.player_id, tp.victories, 
        p.username, p.push_notification_token;
    

    下面的部分真的有必要吗?

     USING player p
        WHERE tp.player_id = p.id 
    

    如果您可以删除此加入,您的查询会更快。我假设tournament_player 中的所有玩家都在player 表中。所以,这个连接是没有必要的。

    【讨论】:

    • 我放置了这个连接部分,因为usernamepush_notification_token 我从player 表而不是player_tournament 表中检索。去掉了还能用吗?
    • 如果您需要这些信息,那么加入是必要的。对不起,我错过了那部分。
    • 能否提供一些文本格式的示例数据,以便我重新创建场景。
    猜你喜欢
    • 2011-10-16
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多