是否可以在Django查询中执行 记录之间的计算?
我知道如何在 记录中执行 计算(例如data_a + data_b)。有没有办法说数据_第0行和第4行(即09-30-17和09-30-16)之间的百分比变化?
+-----------+--------+--------+
| date | data_a | data_b |
+-----------+--------+--------+
| 09-30-17 | 100 | 200 |
| 06-30-17 | 95 | 220 |
| 03-31-17 | 85 | 205 |
| 12-31-16 | 80 | 215 |
| 09-30-16 | 75 | 195 |
+-----------+--------+--------+
我目前正在使用Pandas来执行这些类型的计算,但如果可能的话,我希望消除这一额外步骤。
答案 0 :(得分:1)
我会使用Database cursor raw SQL (见https://docs.djangoproject.com/en/2.0/topics/db/sql/)
结合滞后()窗口函数,如下所示:
result = cursor.execute("""
select date,
data_a - lag(data_a) over (order by date) as data_change,
from foo;""")
这是一般性的想法,您可能需要根据需要进行更改。
答案 1 :(得分:0)
Django数据库中没有第0行,因此我们假设第1行和第5行。
Python中表示的百分比计算通用公式为:
((b - a) / a) * 100
其中a是起始编号,b是结束编号。所以在你的例子中:
a = 100
b = 75
((b - a) / a) * 100
-25.0
如果您的模型名为Foo,则您需要的查询是:
(a, b) = Foo.objects.filter(id__in=[id_1, id_2]).values_list('data_a', flat=True)
values_list
说"得到这些字段"并且flat=True
表示您需要一个简单的值列表,而不是键/值对。通过将其分配给(a, b)
元组并使用__in=
子句,您可以将其作为单个查询而不是两个查询。
我会把它全部包装成一个独立的函数或模型方法:
def pct_change(id_1, id_2):
# Get a single column from two rows and return percentage of change
(a, b) = Foo.objects.filter(id__in=[id_1, id_2]).values_list('data_a', flat=True)
return ((b - a) / a) * 100
然后,如果您知道要比较的两行数据库中的行ID,那么它只是:
print(pct_change(233, 8343))
如果您想逐步计算第1行和第2行之间的变化,然后在第2行和第3行之间进行更改,依此类推,您只需对查询集中的每一行依次运行此函数。由于行ID可能有间隙,因此我们无法使用n + 1来计算下一行。相反,首先获取查询集中所有行ID的列表:
rows = [r.id for r in Foo.objects.all().order_by('date')]
评估为
之类的内容rows = [1,2,3,5,6,9,13]
现在列表中的每个elem和列表中的下一个elem,运行我们的函数:
for (index, row) in enumerate(rows):
if index < len(rows):
current, next_ = row, rows[index + 1]
print(current, next_)
print(pct_change(current, next_))