1

I have a list of id and sort:

ids = ['123', '456', '789', '901'];
sorts = [1, 3, 2, 4];

I want to update the order of each id in Django. Here is the SQL and Django i have tried:

SQL:

UPDATE  "Blogs" 
SET     sort = CASE 
                     WHEN  id = '123' THEN 1
                     WHEN  id = '456' THEN 3
                     WHEN  id = '789' THEN 2
                     WHEN  id = '901' THEN 4
                END
WHERE   id IN (ids);

Django:

Blogs.objects.filter(
            id=ids
        ).update(
            sort=Case(
                When(id=123, then=1),
                When(id=456, then=3),
                When(id=789, then=2),
                When(id=901, then=4),
            )
        )

But problem is when ids have many elements I can not specific id and then in When(id={id}, then={sort}). How can I optimize the update query in Django version. Thanks in advance.

2
  • which db you are using? sqlite3 or mysql? Commented Apr 10, 2017 at 2:03
  • @zhiqianghuang I am using postgresql. Commented Apr 10, 2017 at 2:29

1 Answer 1

1

Django doesn't explicitly provide the functionality you need here. You have already tried it using CASE, WHEN syntax and it would become unmanageable as the number of ids increase.

One solution that I can think of is that you create a temporary table with just (id, sort) column and join on that to update your Blog table.

Here is how you can do this:

  1. Create a temporary table from Blog table using id and sort columns:

    from django.db import connection
    
    cursor = connection.cursor()
    blog_tbl_name = Blog._meta.db_table
    temp_tbl_name = "tmp_{}".format(blog_tbl_name)
    sql = (
         "CREATE TEMP TABLE {temp_tbl_name} AS "
         "SELECT id, sort FROM {blog_tbl_name} LIMIT 0;"
         .format(
             temp_tbl_name=temp_tbl_name,
             blog_tbl_name=blog_tbl_name
         )
    )
    
    cursor.execute(sql)
    
  2. Now, insert the (id, sort) values into this temp table:

    ids = ['123', '456', '789', '901'];
    sorts = [1, 3, 2, 4];
    
    insert_sql = (
        "INSERT INTO {temp_tbl_name} (id, sort) VALUES (%s, %s);"
        .format(temp_tbl_name=temp_tbl_name)
    )
    
    # zip these two together and insert
    cursor.executemany(insert_sql, zip(ids, sorts))
    
  3. Now, the last part where you update the Blog table by joining ids in the temp table:

    update_sql = (
        "UPDATE {blog_tbl_name} blog_tbl "
        "SET sort=tmp_tbl.sort "
        "FROM {temp_tbl_name} tmp_tbl "
        "WHERE blog_tbl.id = tmp_tbl.id;"
        .format(
             temp_tbl_name=temp_tbl_name,
             blog_tbl_name=blog_tbl_name
        )
    )
    
    cursor.execute(update_sql)
    

What is important to note here that this whole process requires only three queries and is manageable and efficient.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.