Как избежать повторения этого подзапроса для предложения IN? - PullRequest
2 голосов
/ 29 марта 2011

У меня есть сценарий SQL (в настоящее время работает на SQLite, но, вероятно, он должен работать на любом механизме БД), который использует один и тот же подзапрос дважды, и, поскольку он может извлекать много записей (таблица содержит пару миллионов строк ) Я хотел бы позвонить только один раз.

Сокращенная псевдо-версия запроса выглядит следующим образом:

SELECT * FROM
    ([the subquery, returns a column of ids]) AS sq
[a couple of joins, that fetches things from other tables based on the ids]
WHERE thisorthat NOT IN ([the subquery again])

Я пытался просто использовать имя (sq) различными способами (с / без скобок, с / без именования столбца sq и т. Д.), Но безрезультатно.

У меня действительно есть , чтобы повторить этот подзапрос?

Пояснение: Я делаю это в python и sqlite как небольшую демонстрацию того, что можно сделать 1016 *, но я бы хотел, чтобы мое решение масштабировалось как можно лучше с минимальными изменениями, насколько это возможно. В реальной ситуации в базе данных будет несколько миллионов строк, но в моем примере всего 10 строк с фиктивными данными. Таким образом, код, который будет хорошо оптимизирован, например, для MySQL , абсолютно достаточно хорош - его не нужно оптимизировать специально для SQLite . Но, как я уже сказал, чем меньше нужно модификаций, тем лучше.

Ответы [ 4 ]

8 голосов
/ 29 марта 2011

В стандартном SQL есть предложение WITH, однако я не знаю, поддерживается ли оно SQLlite, хотя, конечно, стоит попробовать:здесь, вероятно, будет ужасно медленно для любого набора данных, который превышает несколько тысяч строк, поэтому я постараюсь изменить его, если это возможно - NOT IN следует вообще избегать, особенно если у вас также есть пара соединений.1006 *

5 голосов
/ 29 марта 2011

Вам нужен подзапрос?Вы могли бы, вероятно, переписать, используя OUTER JOIN например что-то вроде:

SELECT * 
  FROM [the subquery's FROM clause] AS sq
       RIGHT OUTER JOIN [a couple of tables based on the ids]
          ON thisorthat = sq.[a column of ids]
 WHERE sq.[a column of ids] IS NULL;
1 голос
/ 06 августа 2012

В общем, я подвергаю сомнению необходимость устранения дублирования.Компилятор SQL видит, что два подзапроса идентичны, и решил сделать их только один раз, если это кажется оптимальным.

Кроме того, оставляя дубликаты в источнике, компилятору и оптимизатору SQL предоставляется возможность их обработатьпо-другому.Например, оптимизация сглаживания подзапроса SQLite может применяться к одному из пары дубликатов или применяться по-разному к каждому.См. Раздел 9.0, Уплощение подзапроса https://www.sqlite.org/optoverview.html.

0 голосов
/ 29 марта 2011

вы можете поместить часть SELECT в View, чем фильтровать результаты View, используя псевдоним "sq"

Надеюсь, это полезно

...