【问题标题】:set TableA boolean based on TableB record根据 TableB 记录设置 TableA 布尔值
【发布时间】:2014-03-05 01:26:25
【问题描述】:

我的数据如下所示:

TableA
- id INT
- is_in_table_b BOOL

TableB
- id INT
- table_a_id INT

我在重新组织数据结构时不小心清除了我的开发机器上的 'is_in_table_b' BOOL,我忘记了我是如何创建它的。这只是一些开发基准测试的捷径。

我尝试的所有“UPATE ... FROM ....”变体都基于连接将所有内容设置为“true”。我不记得我最初是否有 CAST。

有谁知道一个简单、优雅的方法来完成这个?如果 TableA.id 出现在 TableB.table_a_id 中,我只想将 is_in_table_b 设置为 True。我知道内部查询的一些不优雅的方法,但我想记住更正确的方法来做到这一点。我很肯定我最初是在“更新自”中完成的。

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    这个应该够简单了:

    UPDATE tableA SET
     is_in_table_b = exists (select 1 FROM tableB WHERE table_a_id=tableA.id);
    

    【讨论】:

    • 哎呀 :) 删除了那个坏链接。
    • 我认为我想要的确切语法是来自 UPDATE table_a SET is_in_b = TRUE FROM table_b WHERE table_b.table_a_id = table_a.id ; 的更新,受 Dan Farrel 在另一个答案中的启发。这可行且简洁,但在我的表结构中效率不高(1700ms vs 41100ms)。
    • @Jonathan:这是一个不同的查询。当 tableB 中没有匹配的条目时,我建议将is_in_b 设置为 false,而对于这些情况,您建议将其保留在之前的 wiped out 状态(可能是 NULL?)。跨度>
    • 是的,你是对的。我必须进行 2 次查询,但首先将全部设置为 NULL 并不会影响性能。我认为更正确的版本是:UPDATE table_a SET is_in_b = CASE WHEN b.table_a_id IS NOT NULL THEN True WHEN b.table_a_id IS NULL THEN False END FROM table_a a LEFT JOIN table_b b ON b.table_a_id = a.id WHERE table_a.id = a.id ;
    【解决方案2】:

    是的,在表之间进行 JOIN 以进行 UPDATE。

    设置:

    CREATE TABLE table_a ( 
      id int not null auto_increment primary key, 
      is_in_b boolean
    );
    CREATE TABLE table_b (
      table_a_id int
    );
    -- create some test data in table_a;
    INSERT INTO table_a (is_in_b) VALUES (FALSE), (FALSE), (FALSE);
    INSERT INTO table_a (is_in_b) SELECT FALSE 
        FROM table_a a1 
        JOIN table_a a2 
        JOIN table_a a3;
    -- and create a subset of matching data in table_a;
    INSERT INTO table_b (table_a_id) 
        SELECT id FROM table_a ORDER BY RAND() limit 5;
    

    现在是答案:

    UPDATE table_a 
      JOIN table_b ON table_a_id = table_a.id
    SET is_in_b = TRUE;
    

    查看结果
    SELECT * from table_b; 
    
    SELECT * FROM table_a WHERE is_in_b;
    

    适用于 http://sqlfiddle.com/#!2/8afc0/1 - 我认为也应该适用于 Postgres。

    【讨论】:

    • 你知道SQLFiddle支持各种版本的PostgreSQL吧?只需从顶部的列表中选择即可。
    • 谢谢。错误的sql,正确的方向。 “更新加入”是 mysql 特有的。 Postgres/其他格式是 "Update From" ,这将是... UPDATE table_a SET is_in_b = TRUE FROM table_b WHERE table_b.table_a_id = table_a.id ;
    【解决方案3】:

    考虑完全删除该冗余列并改用视图或“生成的列”(使用EXISTS expression provided by @Daniel)。此相关问题下的详细信息:
    Store common query as column?

    请确保在TableB.table_a_id 上有一个索引。

    【讨论】:

    • 谢谢。这是一项很棒的技术,适用于其他地方,但不适用于这种特殊情况。我正在使用预先计算的符号字段进行开发中的分析。 Table_a 相对较小,但 table_b 有数千万条记录——即使有索引,在我们当前的 SELECTS 中将其计算为表达式的命中也太大了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多