1

Django is to making a query much more complicated than it needs to be.

A Sentiment may have a User and a Card, and I am getting the Cards which are not in the passed User's Sentiments

This is the query:

Card.objects.all().exclude(sentiments__in=user.sentiments.all())

this is what Django runs:

SELECT * FROM "cards_card" WHERE NOT ("cards_card"."id" IN ( SELECT V1."card_id" AS "card_id" FROM "sentiments_sentiment" V1 WHERE V1."id" IN ( SELECT U0."id" FROM "sentiments_sentiment" U0 WHERE U0."user_id" = 1 ) ) )

This is a version I came up with which didn't do an N-Times full table scan:

Card.objects.raw(' SELECT DISTINCT "id" FROM "cards_card" WHERE NOT "id" IN ( SELECT "card_id" FROM "sentiments_sentiment" WHERE "user_id" = ' + user_id + ' ) )')

I don't know why Django has to do it with the N-Times scan. I've been scouring the web for answers, but nothing so far. Any suggestions on how to keep the performance but not have to fall back to raw SQL?

robert
  • 819
  • 1
  • 10
  • 24
  • I would probably write this as `Card.objects.all().exclude(sentiments__user__id=user.id)`. Does that help at all? – Daniel Roseman Jan 28 '15 at 08:00
  • You are a genius and a scholar! If you answer the question I'll mark it as the answer :). Thank you so much – robert Jan 28 '15 at 09:01

1 Answers1

2

A better way of writing this query without the subqueries would be:

Card.objects.all().exclude(sentiments__user__id=user.id)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895