Как делает В работе предиката в SQL?

Вот пример кода. Вы можете изменить при необходимости

(\/webshop\?(?:product|seksjon)\=\w+)

Проверить результат здесь

20
задан Community 23 May 2017 в 12:34
поделиться

7 ответов

The warning you got about subqueries executing for each row is true -- for correlated subqueries.

SELECT COUNT(*) FROM Table1 a 
WHERE a.Table1id NOT IN (
  SELECT b.Table1Id FROM Table2 b WHERE b.id_user = a.id_user
);

Note that the subquery references the id_user column of the outer query. The value of id_user on each row of Table1 may be different. So the subquery's result will likely be different, depending on the current row in the outer query. The RDBMS must execute the subquery many times, once for each row in the outer query.

The example you tested is a non-correlated subquery. Most modern RDBMS optimizers worth their salt should be able to tell when the subquery's result doesn't depend on the values in each row of the outer query. In that case, the RDBMS runs the subquery a single time, caches its result, and uses it repeatedly for the predicate in the outer query.

PS: In SQL, IN() is called a "predicate," not a statement. A predicate is a part of the language that evaluates to either true or false, but cannot necessarily be executed independently as a statement. That is, you can't just run this as an SQL query: "2 IN (1,2,3);" Although this is a valid predicate, it's not a valid statement.

18
ответ дан 30 November 2019 в 00:01
поделиться

Это будет полностью зависеть от используемой базы данных и точного запроса.

Оптимизаторы запросов иногда бывают очень умными - в вашем примере запроса я ожидал, что лучшие базы данных смогут использовать те же методы, что и при объединении. Более наивные базы данных могут выполнять один и тот же запрос много раз.

8
ответ дан 30 November 2019 в 00:01
поделиться

Это зависит от РСУБД под вопросом.

См. Подробный анализ здесь:

Вкратце:

  1. MySQL оптимизирует запрос к этому:

     SELECT COUNT (*) 
    FROM Table1 t1 
    WHERE NOT EXISTS 
     (
    SELECT 1 
    FROM Table2 t2 
    WHERE t2.id_user = 1 
    AND t2.Table1ID = t1.Table2ID 
    ) 
     

    и выполнить внутренний подзапрос в цикле, используя индекс поиск каждый раз.

    • SQL Server будет использовать MERGE ANTI JOIN .

    Внутренний подзапрос не будет «выполняться» в обычном смысле слова, вместо этого результаты запроса и подзапроса будут извлекаться одновременно.

    Подробное объяснение см. По ссылке выше.

    • Oracle будет использовать HASH ANTI JOIN .

    Внутренний подзапрос будет выполнен один раз, и на основе набора результатов будет построена хэш-таблица.

    Значения внешнего запроса будут найдены в хэш-таблице.

    • PostgreSQL будет использовать НЕ (HASHED SUBPLAN) .

    Очень похоже на Oracle .

Обратите внимание, что переписывание запроса следующим образом:

SELECT  (
        SELECT  COUNT(*)
        FROM    Table1
        ) - 
        (
        SELECT  COUNT(*)
        FROM    Table2 t2
        WHERE   (t2.id_user, t2.Table1ID) IN
                (
                SELECT  1, Table1ID
                FROM    Table1
                )
        )

значительно улучшит производительность во всех четырех системах.

5
ответ дан 30 November 2019 в 00:01
поделиться

Зависит от оптимизатора. Проверьте точный план запроса для каждого конкретного запроса, чтобы увидеть, как СУБД фактически выполнит это.

В Oracle это будет:

EXPLAIN PLAN FOR «your query»

В MySQL или PostgreSQL

EXPLAIN «your query»
4
ответ дан 30 November 2019 в 00:01
поделиться

Большинство движков SQL в настоящее время почти всегда создают один и тот же план выполнения для LEFT JOIN, NOT IN и NOT EXISTS

Я бы сказал, посмотрите на ваш план выполнения и выясните: -)

Также, если у вас есть значения NULL для столбца Table1Id, вы не получите никаких данных обратно

3
ответ дан 30 November 2019 в 00:01
поделиться

Не совсем. Но писать такие запросы просто с помощью JOIN - это просто

0
ответ дан 30 November 2019 в 00:01
поделиться

Да, но выполнение останавливается, как только обработчик запросов "находит" искомое значение ... Итак если, например, первая строка во внешнем выборе имеет Table1Id = 32, и если Table2 имеет запись с TableId = 32, то как только подзапрос находит строку в Table2, где TableId = 32, он останавливается ...

0
ответ дан 30 November 2019 в 00:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: