我们有一个用Django编写的系统来跟踪招募到临床试验的患者。 传播表用于记录整个财政年度每个月招募的患者数量;因此,即使研究可能会持续多年,该表仅包含12个月的数据。
django数据库中有一个表,每个月都会导入电子表格。数据包括月/年,患者数和其他一些领域。每次导入都将包括前几个月的所有数据;我们需要这样做以确保自上次导入后导入表上没有更改数据。
例如,包含两个导入的导入表(第一个截至1月,第二个截至2月)将如下所示:
id | study_id | data_date | patient_count | [other fields] -->
100 5456 2016-04-01 10 ...
101 5456 2016-05-01 8 ...
102 5456 2016-06-01 5 ...
... all months in between ...
109 5456 2016-01-01 12 ...
110 5456 2016-02-01 NULL ...
111 5456 2016-03-01 NULL ...
112 5456 2016-04-01 10 ...
113 5456 2016-05-01 8 ...
114 5456 2016-06-01 5 ...
... all months in between ...
121 5456 2016-01-01 12 ...
122 5456 2016-02-01 6 ...
123 5456 2016-03-01 NULL ...
其他字段包含另一个包含实际研究标识号(iras_number
)的表的外键,因此我必须加入其中以选择特定研究的行。
我希望研究中data_date
和patient_count
的最新值可能超过一个财政年度,因此我尝试了此查询(iras_number
传递给该函数执行此查询):
totals = ImportStudyData.objects.values('data_date', 'patient_count') \
.filter(import_study__iras_number=iras_number) \
.annotate(max_id=Max('id')).order_by()
但是,这会产生一个SQL查询,其patient_count
中包含GROUP BY
,导致重复的行:
data_date | patient_count | max_id
2016-04-01 10 100
2016-04-01 10 112
2016-05-01 8 101
2016-05-01 8 113
...
2016-01-01 12 109
2016-01-01 12 121
2016-02-01 NULL 110
2016-02-01 6 122
如何使用ORM从表格中选择最新的data_date
和patient_count
?
如果我正在编写SQL,我会根据max(id)
对data_date
进行内部选择,然后使用它来加入或使用IN
查询来选择字段我从桌子上要求;如:
SELECT data_date, patient_count
FROM importstudydata
WHERE id IN (
SELECT MAX(id) AS "max_id"
FROM importstudydata INNER JOIN importstudy
ON importstudydata.import_study_id = importstudy.id
WHERE importstudy.iras_number = 5456
GROUP BY importstudydata.data_date
)
ORDER BY data_date ASC
我尝试创建内部选择来复制SQL查询,但内部选择返回多个字段(列)a会导致查询失败:
totals = ImportStudyData.objects.values('data_date', 'patient_count') \
.filter(id__in=ImportStudyData.objects.values('data_date') \
.filter(import_study__iras_number=iras_number) \
.annotate(max_data_id=Max('id'))
现在我无法让内部选择仅返回由{data_date'分组的max(id)
。并且它可以在单个SQL查询中执行。
答案 0 :(得分:0)
现在我将查询分成若干步骤以获得我想要的结果。
首先,我查询与研究相关的所有行的最新id
id_qry = ImportStudyData.objects.values('data_date')\
.filter(import_study__iras_number=iras_number)\
.annotate(max_id=Max('id'))
为了获得仅列出数字的列表,删除日期,我使用列表理解:
id_list = [x['max_id'] for x in id_qry]
然后将此列表用作最终查询的过滤器以获取患者数量
totals = ImportStudyData.objects.values('data_date', 'patient_count') \
.filter(id__in=id_list)
它击中了数据库两次,并且在计算上更加昂贵,但是现在它起作用了,我需要继续前进。
我稍后会回到这个问题。
答案 1 :(得分:-1)
使用:distinct = True
totals = ImportStudyData.objects.values('data_date', 'patient_count').filter(import_study__iras_number=iras_number).annotate(max_id=Max('id')).order_by('data_date').distinct()