Ограничение с использованием неключевого ключа в Django - PullRequest
1 голос
/ 23 июня 2011

В моей базе данных есть пара таблиц (tableA и tableB), обе из которых имеют внешние ключи, ссылающиеся на один и тот же столбец ID в tableC.SQL, который я смог использовать, был

SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID
WHERE tableB.year=2011

Запрос

SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID AND tableB.year=2011

Сделал то же самое

В Django я пытался сделать это с кодом

subquery=tableB.objects.filter(year=2011).values_list(id, flat=True)
results=tableA.objects.filter(id__in=list(subquery))

, как предлагается в документации .Я знаю, что это немного отличается, потому что он возвращает только столбцы в tableA, но я все равно их использую.Код Django казался медленным, я думаю, что частично из-за установленного теста на членство для каждой строки tableA, который очень велик.Есть ли способ сделать это быстрее в Django без использования сырого SQL (который я, очевидно, могу использовать, если мне нужно)?

Ответы [ 3 ]

1 голос
/ 24 июня 2011

Это медленно, потому что он создает запрос, который, вероятно, выглядит как

SELECT * FROM TableA WHERE ID IN (SELECT ID FROM TableB WHERE year=2011)

Как сказал @Udi, было бы лучше, если бы вы могли "django" изменить размеры моделей, добавив некоторые внешние ключи как-нибудь. В противном случае используйте RawSQL. Вот для чего это.

1 голос
/ 24 июня 2011

Не конвертировать subquery в список. Если вы только что сделали это:

results=tableA.objects.filter(id__in=subquery)

Django должен быть достаточно умен, чтобы фактически выполнять подзапрос, а не два отдельных запроса.

1 голос
/ 24 июня 2011

Похоже, что ваши модели не очень дружелюбны к "джанго".Используете ли вы отношения один-к-одному, а ваша таблица pk - это внешние ключи?(Если нет, опубликуйте свою схему в вопросе).Django предпочитает, чтобы первичные ключи вашей таблицы (модели) были уникальными целыми числами с автоматическим приращением, а не внешними ключами.

django, в этом случае это лучше:

class TableC(models.Model):
     name = models.CharField(max_length=1000)

class TableA(models.Model): 
     tablec = models.OneToOneField(TableC)

class TableB(models.Model): 
     tablec = models.OneToOneField(TableC)
     year = models.IntegerField()

Обратите внимание, что все поля имеют (неявный) идентификаторполе, которое является первичным ключом для таблицы.А теперь выполните:

TableA.objects.filter(tablec__tableb__year__exact=2011)

Вы можете фактически использовать внешний ключ в качестве первичного ключа:

class TableC(models.Model):
     name = models.CharField(max_length=1000)

class TableA(models.Model): 
     tablec = models.OneToOneField(TableC, primary_key=True, db_column='id')

class TableB(models.Model): 
     tablec = models.OneToOneField(TableC, primary_key=True, db_column='id')
     year = models.IntegerField()

И выполнить тот же запрос.Однако это может вызвать у вас некоторые проблемы позже («без гарантии»).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...