問題
Django ORMを使用して、SQL _NOT IN
_句と同等のことを行い、IDのリストを副選択に提供して、ログから一連のレコードを取得しようとしていますテーブル。これが可能かどうかわかりません。
モデル
_class JobLog(models.Model):
job_number = models.BigIntegerField(blank=True, null=True)
name = models.TextField(blank=True, null=True)
username = models.TextField(blank=True, null=True)
event = models.TextField(blank=True, null=True)
time = models.DateTimeField(blank=True, null=True)
_
私が試したこと
私の最初の試みはexclude
を使用することでしたが、これはNOT
を使用して、目的の_NOT IN
_ではなくSubquery
全体を否定します。
_query = (
JobLog.objects.values(
"username", "job_number", "name", "time",
)
.filter(time__gte=start, time__lte=end, event="delivered")
.exclude(
job_number__in=models.Subquery(
JobLog.objects.values_list("job_number", flat=True).filter(
time__gte=start, time__lte=end, event="finished",
)
)
)
)
_
残念ながら、これにより次のSQLが生成されます。
_SELECT "view_job_log"."username", "view_job_log"."group", "view_job_log"."job_number", "view_job_log"."name", "view_job_log"."time"
FROM "view_job_log"
WHERE (
"view_job_log"."event" = 'delivered'
AND "view_job_log"."time" >= '2020-03-12T11:22:28.300590+00:00'::timestamptz
AND "view_job_log"."time" <= '2020-03-13T11:22:28.300600+00:00'::timestamptz
AND NOT (
"view_job_log"."job_number" IN (
SELECT U0."job_number"
FROM "view_job_log" U0
WHERE (
U0."event" = 'finished' AND U0."time" >= '2020-03-12T11:22:28.300590+00:00'::timestamptz
AND U0."time" <= '2020-03-13T11:22:28.300600+00:00'::timestamptz
)
)
AND "view_job_log"."job_number" IS NOT NULL
)
)
_
3番目のAND
句を_AND "view_job_log"."job_number" NOT IN
_ではなく_AND NOT (
_にする必要があります。
ここで提案されているように、exclude
を使用して、最初に独自のクエリとして副選択を実行してみました。
ただし、これは同じ問題のある結果をもたらします。次に、Q
オブジェクトを試しましたが、同様のクエリが生成されます。
_query = (
JobLog.objects.values(
"username", "subscriber_code", "job_number", "name", "time",
)
.filter(
~models.Q(job_number__in=models.Subquery(
JobLog.objects.values_list("job_number", flat=True).filter(
time__gte=start, time__lte=end, event="finished",
)
)),
time__gte=start,
time__lte=end,
event="delivered",
)
)
_
Q
オブジェクトを使用したこの試行により、_NOT IN
_なしで、次のSQLが再び生成されます。
_SELECT "view_job_log"."username", "view_job_log"."group", "view_job_log"."job_number", "view_job_log"."name", "view_job_log"."time"
FROM "view_job_log" WHERE (
NOT (
"view_job_log"."job_number" IN (
SELECT U0."job_number"
FROM "view_job_log" U0
WHERE (
U0."event" = 'finished'
AND U0."time" >= '2020-03-12T11:33:28.098653+00:00'::timestamptz
AND U0."time" <= '2020-03-13T11:33:28.098678+00:00'::timestamptz
)
)
AND "view_job_log"."job_number" IS NOT NULL
)
AND "view_job_log"."event" = 'delivered'
AND "view_job_log"."time" >= '2020-03-12T11:33:28.098653+00:00'::timestamptz
AND "view_job_log"."time" <= '2020-03-13T11:33:28.098678+00:00'::timestamptz
)
_
DjangoのORMにAND job_number NOT IN (12345, 12346, 12347)
と同等の機能を実行させる方法はありますか?それとも、これを達成するために生のSQLにドロップする必要がありますか?
このテキスト全体の質問全体を読んでいただき、ありがとうございます。明示的は暗黙的よりも優れています。 :)
あなたはこれを試すことができます:
JobLog.objects.filter(time__gte=start, time__lte=end, event="delivered").exclude(time__gte=start, event='finished').exclude(time__lte=end, event='finished')