【问题标题】:Using window functions in an update statement在更新语句中使用窗口函数
【发布时间】:2011-05-20 12:08:54
【问题描述】:

我有一个通过 Django 访问的大型 PostgreSQL 表。因为 Django 的 ORM 不支持窗口函数,所以我需要将窗口函数的结果作为常规列烘焙到表中。我想做这样的事情:

UPDATE  table_name
SET     col1 = ROW_NUMBER() OVER ( PARTITION BY col2 ORDER BY col3 );

但我得到ERROR: cannot use window function in UPDATE

谁能建议一种替代方法?通过 Django 的 .raw() 方法传递窗口函数语法是不合适的,因为它返回一个 RawQuerySet,它不支持我需要的进一步的 ORM 功能,例如 .filter()。

谢谢。

【问题讨论】:

    标签: sql django postgresql window-functions


    【解决方案1】:

    错误来自 postgres 而不是 django。您可以将其重写为:

    WITH v_table_name AS
    (
        SELECT row_number() over (partition by col2 order by col3) AS rn, primary_key
        FROM table_name
    ) 
    UPDATE table_name set table_name.col1 = v_table_name.rn
    FROM v_table_name
    WHERE table_name.primary_key = v_table_name.primary_key;  
    

    或者:

    UPDATE table_name set table_name.col1 = v_table_name.rn
    FROM  
    (
        SELECT row_number() over (partition by col2 order by col3) AS rn, primary_key
        FROM table_name
    ) AS v_table_name
    WHERE table_name.primary_key = v_table_name.primary_key;
    

    这行得通。刚刚在 postgres-9.6 上测试过。这是UPDATE 的语法(参见可选的fromlist)。

    希望这会有所帮助。

    【讨论】:

    • 我认为您不需要自我加入?我可能错了,因为我是基于 SQL Server 中的工作原理!
    • @Martin:您正在选择两个表,一个是通过 UPDATE tablename 另一个在 FROM tablename 子句中。如果您不明确加入,它将产生笛卡尔积。
    • 第一件事:我不是 sql 大师。我可能错了。如果是,请纠正我。直接来自手册:postgresql.org/docs/current/static/sql-update.htmlfrom_list:表表达式列表,允许来自其他表的列出现在WHERE条件和更新表达式中。这类似于可以在 SELECT 语句的 FROM 子句中指定的表列表。请注意,目标表不得出现在 from_list 中,除非您打算进行自连接(在这种情况下,它必须与别名一起出现在 from_list 中)。
    • 现在我不得不吃我的话了 :( 是的,postgres 没有任何可更新的视图。需要创建规则才能使可更新的视图正常工作。
    • 我需要从SET 语句中省略table_name. 部分,否则效果很好。
    猜你喜欢
    • 2020-06-17
    • 2020-07-09
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 2021-07-02
    • 2022-08-18
    相关资源
    最近更新 更多