Maybe I over simplified the example:
Here is my real example with the full query
new_filter_58 = Q(lang__in=["en", "fr", "nl"]) & (
Q(sources__source_groups__enabled=True, sources__source_groups__tags=58)|Q(keywords__tags=58)
)
new_filter_1 = Q(lang__in=["fr"]) & (
Q(sources__source_groups__enabled=True, sources__source_groups__tags=1)|Q(keywords__tags=1)
)
Here is the correct answer:
pqs = PrimaryPost.objects.filter(created__gt=“2024-03-15”)
count_correct = pqs.filter(new_filter_1).filter(new_filter_58).distinct(“created”, “id”).count()
count_incorrect = pqs.filter(new_filter_1&new_filter_58).distinct(“created”, “id”).count()
query correctly generated is this one:
SELECT
COUNT(*)
FROM
(
SELECT DISTINCT
ON ("gdw_post_pri"."created", "gdw_post_pri"."id") "gdw_post_pri"."id" AS "col1",
"gdw_post_pri"."lang" AS "col2"
FROM
"gdw_post_pri"
LEFT OUTER JOIN "gdw_primarypostsources" ON (
"gdw_post_pri"."id" = "gdw_primarypostsources"."post_id"
)
LEFT OUTER JOIN "gdw_source" ON (
"gdw_primarypostsources"."source_id" = "gdw_source"."id"
)
LEFT OUTER JOIN "gdw_sourcegroup_sources" ON (
"gdw_source"."id" = "gdw_sourcegroup_sources"."source_id"
)
LEFT OUTER JOIN "gdw_sourcegroup" ON (
"gdw_sourcegroup_sources"."sourcegroup_id" = "gdw_sourcegroup"."id"
)
LEFT OUTER JOIN "gdw_sourcegroup_tags" ON (
"gdw_sourcegroup"."id" = "gdw_sourcegroup_tags"."sourcegroup_id"
)
LEFT OUTER JOIN "gdw_primarypostkeyword" ON (
"gdw_post_pri"."id" = "gdw_primarypostkeyword"."post_id"
)
LEFT OUTER JOIN "gdw_keyword" ON (
"gdw_primarypostkeyword"."keyword_id" = "gdw_keyword"."id"
)
LEFT OUTER JOIN "gdw_keyword_tags" ON (
"gdw_keyword"."id" = "gdw_keyword_tags"."keyword_id"
)
LEFT OUTER JOIN "gdw_primarypostsources" T12 ON ("gdw_post_pri"."id" = T12."post_id")
LEFT OUTER JOIN "gdw_source" T13 ON (T12."source_id" = T13."id")
LEFT OUTER JOIN "gdw_sourcegroup_sources" T14 ON (T13."id" = T14."source_id")
LEFT OUTER JOIN "gdw_sourcegroup" T15 ON (T14."sourcegroup_id" = T15."id")
LEFT OUTER JOIN "gdw_sourcegroup_tags" T16 ON (T15."id" = T16."sourcegroup_id")
LEFT OUTER JOIN "gdw_primarypostkeyword" T18 ON ("gdw_post_pri"."id" = T18."post_id")
LEFT OUTER JOIN "gdw_keyword" T19 ON (T18."keyword_id" = T19."id")
LEFT OUTER JOIN "gdw_keyword_tags" T20 ON (T19."id" = T20."keyword_id")
WHERE
(
"gdw_post_pri"."created" > '2024-03-15T00:00:00+00:00'::TIMESTAMPTZ
AND "gdw_post_pri"."lang" IN ('fr')
AND (
(
"gdw_sourcegroup"."enabled"
AND "gdw_sourcegroup_tags"."tag_id" = 1
)
OR "gdw_keyword_tags"."tag_id" = 1
)
AND "gdw_post_pri"."lang" IN ('en', 'fr', 'nl')
AND (
(
T15."enabled"
AND T16."tag_id" = 58
)
OR T20."tag_id" = 58
)
)
ORDER BY
"gdw_post_pri"."created" DESC
) SUBQUERY
query generated incorrectly is this one:
SELECT
COUNT(*)
FROM
(
SELECT DISTINCT
ON ("gdw_post_pri"."created", "gdw_post_pri"."id") "gdw_post_pri"."id" AS "col1",
"gdw_post_pri"."lang" AS "col2"
FROM
"gdw_post_pri"
LEFT OUTER JOIN "gdw_primarypostsources" ON (
"gdw_post_pri"."id" = "gdw_primarypostsources"."post_id"
)
LEFT OUTER JOIN "gdw_source" ON (
"gdw_primarypostsources"."source_id" = "gdw_source"."id"
)
LEFT OUTER JOIN "gdw_sourcegroup_sources" ON (
"gdw_source"."id" = "gdw_sourcegroup_sources"."source_id"
)
LEFT OUTER JOIN "gdw_sourcegroup" ON (
"gdw_sourcegroup_sources"."sourcegroup_id" = "gdw_sourcegroup"."id"
)
LEFT OUTER JOIN "gdw_sourcegroup_tags" ON (
"gdw_sourcegroup"."id" = "gdw_sourcegroup_tags"."sourcegroup_id"
)
LEFT OUTER JOIN "gdw_primarypostkeyword" ON (
"gdw_post_pri"."id" = "gdw_primarypostkeyword"."post_id"
)
LEFT OUTER JOIN "gdw_keyword" ON (
"gdw_primarypostkeyword"."keyword_id" = "gdw_keyword"."id"
)
LEFT OUTER JOIN "gdw_keyword_tags" ON (
"gdw_keyword"."id" = "gdw_keyword_tags"."keyword_id"
)
WHERE
(
"gdw_post_pri"."created" > '2024-03-15T00:00:00+00:00'::TIMESTAMPTZ
AND "gdw_post_pri"."lang" IN ('fr')
AND (
(
"gdw_sourcegroup"."enabled"
AND "gdw_sourcegroup_tags"."tag_id" = 1
)
OR "gdw_keyword_tags"."tag_id" = 1
)
AND "gdw_post_pri"."lang" IN ('en', 'fr', 'nl')
AND (
(
"gdw_sourcegroup"."enabled"
AND "gdw_sourcegroup_tags"."tag_id" = 58
)
OR "gdw_keyword_tags"."tag_id" = 58
)
)
ORDER BY
"gdw_post_pri"."created" DESC
) SUBQUERY
As you can see there is quite a few table joins involved in my example, but that does not matter too much, the source of the difference is that
qs.filter(A).filter(B) handle the query has different table joins (that is well documented in the documentation, don’t remember where though)
qs.filter(A&B) handle the query on related tables as a single join, and I would like to be able to tell my combined Q func A&B to use different joined tables instead of reusing the same table joins.
I hope the problem is clear and someone can help with this.
Loic,