代码之家  ›  专栏  ›  技术社区  ›  Alexander Farber

更新。。。来自不同的列,具体取决于条件

  •  0
  • Alexander Farber  · 技术社区  · 7 年前

    我准备了一个简单的 SQL Fiddle 回答我的问题。

    在PostgreSQL中,10个用户ID存储在 words_users 表,但其名称存储在 words_social 表格:

    CREATE TABLE words_users (
            uid     SERIAL PRIMARY KEY
    );
    
    CREATE TABLE words_social (
            sid     text     NOT NULL,
            social  integer  NOT NULL CHECK (0 < social AND social <= 64),
            given   text     NOT NULL CHECK (given ~ '\S'),
            uid     integer  NOT NULL REFERENCES words_users ON DELETE CASCADE,
            PRIMARY KEY(sid, social)
    );
    
    INSERT INTO words_users (uid) VALUES (1), (2);
    
    INSERT INTO words_social (sid, social, given, uid) VALUES 
    ('1111', 10, 'Alice', 1), 
    ('2222', 20, 'Bob', 2);
    

    两人游戏存储在下表中 chat1 chat2 包含新聊天信息数的列 player1 player2 (在这里,Alice和Bob都有一条新消息在游戏中等待#100):

    CREATE TABLE words_games (
            gid SERIAL PRIMARY KEY,
            player1 integer REFERENCES words_users(uid) ON DELETE CASCADE NOT NULL CHECK (player1 <> player2),
            player2 integer REFERENCES words_users(uid) ON DELETE CASCADE,
            chat1 integer NOT NULL,
            chat2 integer NOT NULL
    );
    
    INSERT INTO words_games (gid, player1, player2, chat1, chat2) 
    VALUES (100, 1, 2, 1, 1);
    

    当用户阅读她的聊天信息时,我想重置相应的列( 聊天室1 聊天室2 )返回到0。

    我不能使用 uid 要识别用户,我必须通过 sid social

    因此,我正在尝试重置游戏#100中Bob的新聊天信息数:

    UPDATE words_games g
    SET    CASE WHEN s.uid = g.player1 THEN chat2 = 0 ELSE chat1 = 0 END
    FROM   words_social s
    WHERE  g.gid    = 100
    AND    s.social = 20
    AND    s.sid    = '2222'
    AND    s.uid IN (g.player1, g.player2);
    

    但是得到一个语法错误,因为 CASE 不允许存在。

    这里有谁有好的建议吗?

    我问题的背景是我已经 a working stored function in pl/pgSQL 但希望切换到纯SQL以获得更好的性能。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Gordon Linoff    7 年前

    您可以使用两个单独的 set 条款:

    UPDATE word_games g
        SET chat2 = (CASE WHEN s.uid = g.player1 THEN 0 ELSE chat2 END),
            chat1 = (CASE WHEN s.uid = g.player1 THEN chat1 ELSE 0 END)
        . . .