【问题标题】:Sort table by a column and set other column to sequential value to persist ordering按列对表进行排序并将其他列设置为顺序值以保持排序
【发布时间】:2013-06-11 19:20:53
【问题描述】:

所以我不确定是否将其作为 Django 或 SQL 问题提出,但是我有以下模型:

class Picture(models.Model):
    weight = models.IntegerField(default=0)
    taken_date = models.DateTimeField(blank=True, null=True)
    album = models.ForeignKey(Album, db_column="album_id", related_name='pictures')

我可能有数以千计的图片记录子集,我需要按taken_date 对它们进行排序,并通过设置weight 值来保持顺序。

例如在 Django 中:

pictures = Picture.objects.filter(album_id=5).order_by('taken_date')
for weight, picture in enumerate(list(pictures)):
    picture.weight = weight
    picture.save()

现在,我预计会有 1000 条记录,这可能需要很长时间。有没有更有效的方法来执行这项任务?我假设我可能需要求助于 SQL,因为我最近开始学习 Django 在数据库批量操作方面不一定“还存在”。

【问题讨论】:

  • 示例代码是否将权重设置为当前值?我看不到实际更新的地方,还是我遗漏了什么?
  • 在原始查询集和 SQL 中,我为每行创建一个 weight 值,它是一个序列号,根本不是从原始记录中获取的,然后应用该权重值为picture.weight
  • 请添加您的解决方案作为您自己问题的答案。这让以后会查看此问题的其他人更清楚,并允许您的答案被投票赞成/反对,并与可能给出的其他答案进行比较。

标签: python mysql django django-1.4


【解决方案1】:

好的,我将以下内容放在 MySQL 中,效果很好,但是我猜没有办法使用 Django ORM 来模拟这个?

UPDATE picture p
JOIN (SELECT @inc := @inc + 1 AS new_weight, id 
FROM (SELECT @inc := 0) temp, picture 
WHERE album_id = 5 
ORDER BY taken_date) pw
ON p.id = pw.id
SET p.weight = pw.new_weight;

我会把这个问题留一会儿,以防万一有一些很棒的解决方案或应用程序可以解决这个问题,但是上面对约 6000 条记录的查询需要 0.11 秒。

注意如果您在 MySQL 中有以下设置,上述查询将在 MySQL 中生成警告:

binlog_format=statement

要解决此问题,您必须将binlog_format 设置更改为mixedrowmixed 可能更好,因为这意味着您仍将使用statement 处理所有内容,除非需要row 以避免出现上述警告。

【讨论】:

  • 这似乎运行得更快一点:UPDATE page AS m_change RIGHT JOIN (select @i:=@i+10 as rank, m.id as id from page as m, (SELECT @i: =0) as r where app='somefilter' order by m.sequence asc) AS m_rank ON m_change.id = m_rank.id set sequence=rank;
猜你喜欢
  • 2011-02-03
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 2017-04-08
  • 2020-12-20
  • 1970-01-01
相关资源
最近更新 更多