Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using window functions in an update statement

I have a large PostgreSQL table which I access through Django. Because Django's ORM does not support window functions, I need to bake the results of a window function into the table as a regular column. I want to do something like this:

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

But I get ERROR: cannot use window function in UPDATE

Can anyone suggest an alternative approach? Passing the window function syntax through Django's .raw() method is not suitable, as it returns a RawQuerySet, which does not support further ORM features such as .filter(), which I need.

Thanks.

like image 668
jl6 Avatar asked Dec 05 '10 11:12

jl6


People also ask

Can we use function in UPDATE statement?

You can't use the UPDATE statement inside a function unless the UPDATE statement is directed to a table variable local to the function.

Can we use window function in case statement?

If the query executes, the window function supports the CASE Expression . While it is possible to use the CASE Expression in the PARTITION BY clause, I've rarely used it on projects.

When should we use window function?

Window functions increase the efficiency and reduce the complexity of queries that analyze partitions (windows) of a data set by providing an alternative to more complex SQL concepts, e.g. derived queries. Common use cases include: Ranking results within a specific window (e.g. per-group ranking)

What is the use of window functions in SQL?

A window function performs a calculation across a set of table rows that are somehow related to the current row. This is comparable to the type of calculation that can be done with an aggregate function.


1 Answers

The error is from postgres not django. You can rewrite this as:

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;   

Or alternatively:

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; 

This works. Just tested it on postgres-9.6. Here is the syntax for UPDATE (see the optional fromlist).

Hope this helps.

like image 79
Max Avatar answered Sep 19 '22 15:09

Max