【问题标题】:Django: join on DateTimeFieldDjango:加入 DateTimeField
【发布时间】:2023-03-11 00:55:02
【问题描述】:

如何在 DateTimeField 上加入两个模型?

class ExchangeRate(models.Model):
    date = models.DateTimeField(...)
    usd_rub = models.DecimalField(...)

class LedgerEntry(models.Model):
    account = models.ForeignKey(...)
    date = models.DateTimeField(...)
    amount = models.DecimalField(...)

这是我想要的一个例子。请注意,ExchangeRate 表中的记录具有任意日期和时间(与 LedgerEntry 表中的日期不对应)。可以仅在日期或小时内加入 ExchangeRates(忽略分钟、秒等是安全的)

        ExchangeRate                        LedgerEntry            
–––––––––––––––––––––––––––-    –––––––––––––––––––––––––––---------
|      Date     |  USD_RUB |    | account |      Date     | Amount |
|---------------|----------|    |–––––––––|---------------|--------|
| 29 Nov, 14:15 |  100.00  |    |    13   | 29 Nov, 14:40 |  10.0  |
| 29 Nov, 14:04 |  200.00  |    |    37   | 29 Nov, 14:45 |  11.0  |
| 29 Nov, 13:51 |  150.00  |    |    19   | 01 Oct, 10:32 |  12.0  |
| ............. | .........|    –––––––––––––––––––––––––––---------
| 01 Oct, 10:23 |  500.00  |
–––––––––––––––––––––––––––-

                           Join result                             
–––––––––––––––––––––––––––-------------------------------------
| account |      Date     | Amount |  USD_RUB | USD_RUB amount |
|–––––––––|---------------|--------|----------|----------------|
|    13   | 29 Nov, 14:40 |  10.0  |  100.00  |    1000.0      |
|    37   | 29 Nov, 14:45 |  11.0  |  100.00  |    1100.0      |
|    19   | 01 Oct, 10:32 |  12.0  |  500.00  |    6000.0      |
–––––––––––––––––––––––––––-------------------------------------

我知道我可以从数据库中查询所有这些对象并在 Python 中“加入”它们。数据库中有数千条记录,因此效率非常低,因为在为分类帐条目查找相应汇率时会产生大量的单选语句。

【问题讨论】:

    标签: python sql django django-orm


    【解决方案1】:

    起初我想使用原始 SQL 进行左连接,但我找到了使用 extra() 的解决方案:

    referral_profits = LedgerEntry.objects.filter(
        balance=request.user.balance,
        reason=LedgerEntry.REASON_DEBIT
    ).extra(
        select={ 'usd_value': r'''
            SELECT usd_rub
            FROM stats_exchangerate
            WHERE 
                date_trunc('hour', billing_ledgerentry.date) = 
                date_trunc('hour', stats_exchangerate.date)
            LIMIT 1
            '''
        },
    )
    for x in referral_profits:
        print(x, x.usd_value, x.date)
    

    请注意,date_trunc 是 Postgres 特有的函数。

    编辑:它有效,但效率极低。看来不得已的办法是使用纯 SQL?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-05
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-26
      相关资源
      最近更新 更多