Python 使用相同的列值更新数据库的最新行

Python 使用相同的列值更新数据库的最新行,python,sql,django,Python,Sql,Django,我有一张如下表: ------------------------------------------------------ | year | period | publish_date | status | -----------|-------------|---------------|-----------| | 2020 | 03 | datetime_obj | 0 | | 2020 | 03

我有一张如下表:

------------------------------------------------------
| year     |  period     |  publish_date |  status   |
-----------|-------------|---------------|-----------|
|  2020    |     03      |  datetime_obj |     0     |
|  2020    |     03      |  ...          |     0     |
|  2020    |     03      |  ...          |     0     |
|  2020    |     03      |  ...          |     0     |
|  2020    |     04      |  ...          |     0     |
|  2020    |     04      |  ...          |     0     |
------------------------------------------------------

我想在任何年份和期间组中更新最新发布日期的状态,但对此我没有任何想法

例如:
选择2020年期间为03的所有行,然后将最新发布日期的stauts更新为1,然后对2020年期间为04的行执行相同的操作,直到结束…
我想在django中使用它,所以请用pythonic方式或sql查询进行解释

这是我的django型号:

class Balance_Sheet(models.Model):
    ...
    publish_date = models.DateTimeField(auto_now=True) 
    year = models.IntegerField(null=True)
    period = models.IntegerField(null=True) 
    status = models.IntegerField(default=0)  
    ...

非常感谢

我不熟悉django,但是它的sql看起来是这样的。因为你们已经有了资产负债表。您只需要更新部分

WITH balance_sheet(id ,yearmonth , publish_date, status)
AS (SELECT 1, '202003',  '2020-03-10' , 0   UNION 
    SELECT 2, '202003',  '2020-03-15' , 0   UNION
    SELECT 3, '202004',  '2020-04-20' , 0   UNION
    SELECT 4, '202004',  '2020-04-25' , 0
   )

UPDATE b
SET status = 1
FROM balance_sheet b
JOIN (Select *,RANK() OVER (partition by yearmonth ORDER BY publish_date desc) AS rnk 
from balance_sheet bal) b_latest ON b.id = b_latest.id
WHERE b_latest.rnk = 1

我不熟悉django,但是它的sql应该是这样的。因为你们已经有了资产负债表。您只需要更新部分

WITH balance_sheet(id ,yearmonth , publish_date, status)
AS (SELECT 1, '202003',  '2020-03-10' , 0   UNION 
    SELECT 2, '202003',  '2020-03-15' , 0   UNION
    SELECT 3, '202004',  '2020-04-20' , 0   UNION
    SELECT 4, '202004',  '2020-04-25' , 0
   )

UPDATE b
SET status = 1
FROM balance_sheet b
JOIN (Select *,RANK() OVER (partition by yearmonth ORDER BY publish_date desc) AS rnk 
from balance_sheet bal) b_latest ON b.id = b_latest.id
WHERE b_latest.rnk = 1

解决方案1

一个简单的解决方法是应用过滤器在年/月内迭代:

years = {sheet.year for sheet in Balance_Sheet.objects.all()}

for year in years:
  year_months = {sheet.month for sheet in Balance_Sheet.objects.filter(year=year)}

  for month in year_months:
    object_to_update = Balance_Sheet.objects.filter(
      year=year,
      period=month
    ).order_by('-publish_date').first()

    object_to_update.status = 1
    object_to_update.save()
可能会有更复杂的ORM函数将其转换为单个查询,但我在那里编写的代码(未经测试)将在大多数/所有Django版本中运行。此外,对数据库的查询量不会很大,因为我们讨论的是年/月数量

解决方案2

在postgres数据库中,您可以尝试以下操作:

Balance_Sheet.objects.all().order_by(
    'year', 'period', '-publish_date'
).distinct(
    'year', 'period'
).update(
    status=1
)

请注意,这在其他数据库(如MySQL)中不起作用。请参阅django文档。

解决方案1

一个简单的解决方法是应用过滤器在年/月内迭代:

years = {sheet.year for sheet in Balance_Sheet.objects.all()}

for year in years:
  year_months = {sheet.month for sheet in Balance_Sheet.objects.filter(year=year)}

  for month in year_months:
    object_to_update = Balance_Sheet.objects.filter(
      year=year,
      period=month
    ).order_by('-publish_date').first()

    object_to_update.status = 1
    object_to_update.save()
可能会有更复杂的ORM函数将其转换为单个查询,但我在那里编写的代码(未经测试)将在大多数/所有Django版本中运行。此外,对数据库的查询量不会很大,因为我们讨论的是年/月数量

解决方案2

在postgres数据库中,您可以尝试以下操作:

Balance_Sheet.objects.all().order_by(
    'year', 'period', '-publish_date'
).distinct(
    'year', 'period'
).update(
    status=1
)
请注意,这在其他数据库(如MySQL)中不起作用。请参阅django文档。

这是mysql中的工作

UPDATE Balance_Sheet b
    INNER JOIN (SELECT max(publish_date) LastDate, year, period FROM bs GROUP BY year, period) C
    ON C.LastDate = b.publish_date and C.period = b.period and C.year = b.year
SET b.status = 1
where C.LastDate = b.publish_date and C.period = b.period and C.year = b.year
感谢mysql中的所有工作

UPDATE Balance_Sheet b
    INNER JOIN (SELECT max(publish_date) LastDate, year, period FROM bs GROUP BY year, period) C
    ON C.LastDate = b.publish_date and C.period = b.period and C.year = b.year
SET b.status = 1
where C.LastDate = b.publish_date and C.period = b.period and C.year = b.year

谢谢大家

此表的django模型在哪里?@roganjosh我在说明中添加了我的django模型此表的django模型在哪里?@roganjosh我在说明中添加了我的django模型,但这可能是一个大问题。只是我的测试数据是52000行@DanialEshghi您使用的是哪个django版本和数据库?这些东西在mysql和postgresql之间可能会发生变化。@DanialEshghi您想要执行的操作听起来像是一个维护操作。比如说,每天运行一次我编写的代码并没有问题。假设你有50年或100年的出版物,在最坏的情况下,每年会运行13个查询。如果您必须经常运行此操作,则可以方便地重构系统,以便在条件满足时自动更新状态字段。是的,数据库可能会改变一切。在出现这个问题之前,我认为每个sql数据库都是相似的,但有了这个问题,我知道它们之间存在着多少差异。谢谢你关于第二条评论:这个操作每小时运行一次,我还有一个外键列
ref\u id
属于大约1000行。这52000行仅适用于1
ref\u id
和10年。实际上,我的数据约为30年或更长。是的,但这可能是一个大问题。只是我的测试数据是52000行@DanialEshghi您使用的是哪个django版本和数据库?这些东西在mysql和postgresql之间可能会发生变化。@DanialEshghi您想要执行的操作听起来像是一个维护操作。比如说,每天运行一次我编写的代码并没有问题。假设你有50年或100年的出版物,在最坏的情况下,每年会运行13个查询。如果您必须经常运行此操作,则可以方便地重构系统,以便在条件满足时自动更新状态字段。是的,数据库可能会改变一切。在出现这个问题之前,我认为每个sql数据库都是相似的,但有了这个问题,我知道它们之间存在着多少差异。谢谢你关于第二条评论:这个操作每小时运行一次,我还有一个外键列
ref\u id
属于大约1000行。这52000行仅用于1
ref\u id
和10年,实际上,我的数据大约是30年甚至更长