#28297: Same queryset result in two different queries on ORM -------------------------------------+------------------------------------- Reporter: Marcus Renno | Owner: nobody Type: Uncategorized | Status: new Component: Database layer | Version: 1.11 (models, ORM) | Severity: Normal | Resolution: Keywords: join, annotation, F | Triage Stage: | Unreviewed Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+------------------------------------- Description changed by Marcus Renno:
Old description: > Sometimes when I run a set of filter/annotation the result is different > for the same variables. > > This is the queryset command: > > {{{ > ingredients = ['tomato'] > self.queryset = Recipe.objects.all() > self.queryset = > self.queryset.annotate(total=Count('steps__ingredients', distinct=True)) > self.queryset = > self.queryset.filter(steps__ingredients__ingredient__name__in=ingredients) > self.queryset = > self.queryset.annotate(available=Count('steps__ingredients', > distinct=True)) > self.queryset = self.queryset.filter(total=F('available')) > }}} > > This is the wrong query result that comes often times: > > {{{ > SELECT recipebook_recipe.id, recipebook_recipe.name, > recipebook_recipe.dificulty, recipebook_recipe.duration, COUNT(DISTINCT > recipebook_steprecipe_ingredients.recipeingredient_id) AS total, > COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) AS > available FROM recipebook_recipe LEFT OUTER JOIN recipebook_recipe_steps > ON (recipebook_recipe.id = recipebook_recipe_steps.recipe_id) LEFT OUTER > JOIN recipebook_steprecipe ON (recipebook_recipe_steps.steprecipe_id = > recipebook_steprecipe.id) LEFT OUTER JOIN > recipebook_steprecipe_ingredients ON (recipebook_steprecipe.id = > recipebook_steprecipe_ingredients.steprecipe_id) INNER JOIN > recipebook_recipe_steps T6 ON (recipebook_recipe.id = T6.recipe_id) INNER > JOIN recipebook_steprecipe T7 ON (T6.steprecipe_id = T7.id) INNER JOIN > recipebook_steprecipe_ingredients T8 ON (T7.id = T8.steprecipe_id) INNER > JOIN recipebook_recipeingredient T9 ON (T8.recipeingredient_id = T9.id) > INNER JOIN recipebook_ingredient ON (T9.ingredient_id = > recipebook_ingredient.id) WHERE recipebook_ingredient.name IN ("tomato") > GROUP BY recipebook_recipe.id HAVING COUNT(DISTINCT > recipebook_steprecipe_ingredients.recipeingredient_id) = (COUNT(DISTINCT > recipebook_steprecipe_ingredients.recipeingredient_id)) ORDER BY NULL > }}} > > And this is the right query that shows up sometimes: > > {{{ > SELECT recipebook_recipe.id, recipebook_recipe.name, > recipebook_recipe.dificulty, recipebook_recipe.duration, COUNT(DISTINCT > recipebook_steprecipe_ingredients.recipeingredient_id) AS total, > COUNT(DISTINCT T8.recipeingredient_id) AS available FROM > recipebook_recipe LEFT OUTER JOIN recipebook_recipe_steps ON > (recipebook_recipe.id = recipebook_recipe_steps.recipe_id) LEFT OUTER > JOIN recipebook_steprecipe ON (recipebook_recipe_steps.steprecipe_id = > recipebook_steprecipe.id) LEFT OUTER JOIN > recipebook_steprecipe_ingredients ON (recipebook_steprecipe.id = > recipebook_steprecipe_ingredients.steprecipe_id) INNER JOIN > recipebook_recipe_steps T6 ON (recipebook_recipe.id = T6.recipe_id) INNER > JOIN recipebook_steprecipe T7 ON (T6.steprecipe_id = T7.id) INNER JOIN > recipebook_steprecipe_ingredients T8 ON (T7.id = T8.steprecipe_id) INNER > JOIN recipebook_recipeingredient T9 ON (T8.recipeingredient_id = T9.id) > INNER JOIN recipebook_ingredient ON (T9.ingredient_id = > recipebook_ingredient.id) WHERE recipebook_ingredient.name IN ("tomato") > GROUP BY recipebook_recipe.id HAVING COUNT(DISTINCT > recipebook_steprecipe_ingredients.recipeingredient_id) = (COUNT(DISTINCT > T8.recipeingredient_id)) ORDER BY NULL > }}} > > As you can see they are different. The wrong one does not set the > variable 'available' appropriately. I wonder if this is something on the > method `.query.join()` New description: Sometimes when I run a set of filter/annotation the result is different for the same variables. This is the queryset command: {{{ ingredients = ['tomato'] self.queryset = Recipe.objects.all() self.queryset = self.queryset.annotate(total=Count('steps__ingredients', distinct=True)) self.queryset = self.queryset.filter(steps__ingredients__ingredient__name__in=ingredients) self.queryset = self.queryset.annotate(available=Count('steps__ingredients', distinct=True)) self.queryset = self.queryset.filter(total=F('available')) }}} This is the wrong query result that comes often times: {{{ SELECT recipebook_recipe.id, recipebook_recipe.name, recipebook_recipe.dificulty, recipebook_recipe.duration, COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) AS total, COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) AS available FROM recipebook_recipe LEFT OUTER JOIN recipebook_recipe_steps ON (recipebook_recipe.id = recipebook_recipe_steps.recipe_id) LEFT OUTER JOIN recipebook_steprecipe ON (recipebook_recipe_steps.steprecipe_id = recipebook_steprecipe.id) LEFT OUTER JOIN recipebook_steprecipe_ingredients ON (recipebook_steprecipe.id = recipebook_steprecipe_ingredients.steprecipe_id) INNER JOIN recipebook_recipe_steps T6 ON (recipebook_recipe.id = T6.recipe_id) INNER JOIN recipebook_steprecipe T7 ON (T6.steprecipe_id = T7.id) INNER JOIN recipebook_steprecipe_ingredients T8 ON (T7.id = T8.steprecipe_id) INNER JOIN recipebook_recipeingredient T9 ON (T8.recipeingredient_id = T9.id) INNER JOIN recipebook_ingredient ON (T9.ingredient_id = recipebook_ingredient.id) WHERE recipebook_ingredient.name IN ("tomato") GROUP BY recipebook_recipe.id HAVING COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) = (COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id)) ORDER BY NULL }}} And this is the right query that shows up sometimes: {{{ SELECT recipebook_recipe.id, recipebook_recipe.name, recipebook_recipe.dificulty, recipebook_recipe.duration, COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) AS total, COUNT(DISTINCT T8.recipeingredient_id) AS available FROM recipebook_recipe LEFT OUTER JOIN recipebook_recipe_steps ON (recipebook_recipe.id = recipebook_recipe_steps.recipe_id) LEFT OUTER JOIN recipebook_steprecipe ON (recipebook_recipe_steps.steprecipe_id = recipebook_steprecipe.id) LEFT OUTER JOIN recipebook_steprecipe_ingredients ON (recipebook_steprecipe.id = recipebook_steprecipe_ingredients.steprecipe_id) INNER JOIN recipebook_recipe_steps T6 ON (recipebook_recipe.id = T6.recipe_id) INNER JOIN recipebook_steprecipe T7 ON (T6.steprecipe_id = T7.id) INNER JOIN recipebook_steprecipe_ingredients T8 ON (T7.id = T8.steprecipe_id) INNER JOIN recipebook_recipeingredient T9 ON (T8.recipeingredient_id = T9.id) INNER JOIN recipebook_ingredient ON (T9.ingredient_id = recipebook_ingredient.id) WHERE recipebook_ingredient.name IN ("tomato") GROUP BY recipebook_recipe.id HAVING COUNT(DISTINCT recipebook_steprecipe_ingredients.recipeingredient_id) = (COUNT(DISTINCT T8.recipeingredient_id)) ORDER BY NULL }}} As you can see they are different. The wrong one does not set the variable 'available' appropriately. I wonder if this is something on the method `.query.join()` -- -- Ticket URL: <https://code.djangoproject.com/ticket/28297#comment:1> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/069.c3d57f103b703e8f796c17b103f389f2%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.