我正在使用 Postgresql。我有模型:
class EventsList(CreatedUpdatedMixin):
start = models.DateTimeField()
end = models.DateTimeField()
is_inner = models.BooleanField()
假設我有這些資料庫條目:
| 開始 | 結尾 | is_inner |
|---|---|---|
| 2021-12-09 14:30:12 | 2021-12-09 15:00:21 | 真的 |
| 2021-12-09 14:00:05 | 2021-12-10 21:00:15 | 錯誤的 |
| 2021-12-10 09:00:39 | 2021-12-10 09:30:50 | 真的 |
| 2021-12-10 14:00:00 | 2021-12-11 15:00:00 | 真的 |
| 2021-12-14 10:00:00 | 2021-12-14 11:00:00 | 真的 |
| 2021-12-13 13:30:00 | 2021-12-16 14:30:00 | 錯誤的 |
| 2021-12-14 13:10:00 | 2021-12-15 00:30:00 | 真的 |
| 2021-12-14 10:30:00 | 2021-12-16 13:34:00 | 錯誤的 |
| 2021-12-15 13:30:00 | 2021-12-15 18:30:00 | 真的 |
這是我需要的結果:
[
{"2021-12-09": {"external_events": 1, "internal_events": 1}},
{"2021-12-10": {"external_events": 0, "internal_events": 2}},
{"2021-12-11": {"external_events": 0, "internal_events": 1}},
{"2021-12-13": {"external_events": 1, "internal_events": 0}},
{"2021-12-14": {"external_events": 2, "internal_events": 2}},
{"2021-12-15": {"external_events": 2, "internal_events": 2}},
{"2021-12-16": {"external_events": 2, "internal_events": 0}},
]
所以我想獲取所有現有日期,并為每個日期獲取外部事件的計數(其中 is_inner == False)和內部事件的計數(其中 is_inner == True)。如何使用 Django ORM 或原始 SQL 來實作?現在,我想出了
EventsList.objects.annotate(
start_day=Cast("start", output_field=DateField())
).values("start_day").annotate(
external_events=Count("id", filter=Q(is_inner=False)),
internal_events=Count("id", filter=Q(is_inner=True)),
).values(
"start_day", "external_events", "internal_events"
)
此代碼回傳幾乎正確的結果(但僅適用于“開始”日期)。我需要包括所有日期(開始日期、結束日期以及它們之間的所有日期)。將不勝感激任何幫助。
uj5u.com熱心網友回復:
使用原始 SQL,首先使用擴展日期串列,generate_series然后lateral join進行條件聚合。所以在這里,有點冗長,但我希望易于閱讀。
SQL小提琴
with t as
(
select is_inner, d::date from the_table
cross join lateral generate_series
(
date_trunc('day', "start"),
date_trunc('day', "end"),
interval '1 day'
) as d
)
select d as event_date,
count(*) filter (where not is_inner) external_events,
count(*) filter (where is_inner) internal_events
from t
group by d order by d;
您也可以使用以下方式塑造問題中的 JSON 結構jsonb_build_object:
with t as
(
select is_inner, d::date from the_table
cross join lateral generate_series
(
date_trunc('day', "start"),
date_trunc('day', "end"),
interval '1 day'
) as d
)
select jsonb_build_object
(
d::text,
jsonb_build_object('external_events', count(*) filter (where not is_inner),
'internal_events', count(*) filter (where is_inner))
) as date_info
from t
group by d order by d;
| 日期資訊 |
|---|
| {“2021-12-09”:{“external_events”:1,“internal_events”:1}} |
| {“2021-12-10”:{“external_events”:1,“internal_events”:2}} |
| {“2021-12-11”:{“external_events”:0,“internal_events”:1}} |
| {“2021-12-13”:{“external_events”:1,“internal_events”:0}} |
| {“2021-12-14”:{“external_events”:2,“internal_events”:2}} |
| {“2021-12-15”:{“external_events”:2,“internal_events”:2}} |
| {“2021-12-16”:{“external_events”:2,“internal_events”:0}} |
uj5u.com熱心網友回復:
首先,要獲取不在您的資料庫中的所有日期,您將在最大和最小日期之間回圈以獲取所有日期,并為每個日期運行查詢以匹配您想要的過濾器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/410935.html
標籤:
