SQL Server - короткое замыкание запроса?

Поддерживают ли запросы T-SQL в SQL Server короткое замыкание?

Например, у меня есть ситуация, когда у меня есть две базы данных, и я сравниваю данные между двумя таблицами, чтобы сопоставить и скопировать некоторую информацию. В одной таблице поле «ID» всегда будет иметь ведущие нули (например, «000000001234»), а в другой таблице поле идентификатора может иметь или не иметь начальные нули (может быть «000000001234» или «1234»).

Итак, мой запрос на сопоставление этих двух выглядит примерно так: выберите * from table1, где table1.ID LIKE '% 1234'

Чтобы ускорить процесс, я подумываю добавить ИЛИ до того, как будет сказано: table1.ID = table2.ID для обработки случая, когда оба идентификатора имеют заполненные нулями и равны.

Ускоряет ли это запрос, сопоставляя элементы в «=» и не оценивая LIKE для каждой отдельной строки (произойдет ли короткое замыкание и пропустить LIKE)?

Как насчет table1.ID LIKE "% 1234" будет соответствовать "31234"?

Dennis C 19.12.2008 18:35

Что ж, фильтр поиска будет больше похож на "% 00001234" - все еще есть некоторые ведущие нули.

Sam Schutte 19.12.2008 19:16
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
4
2
3 183
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

исправить базу данных, чтобы она была согласованной

select * from table1 where table1.ID LIKE '%1234'

будет соответствовать '1234', '01234', '00000000001234', но также и '999991234'. Использование LIKE в значительной степени гарантирует сканирование индекса (при условии, что table1.ID проиндексирован!). Очистка данных значительно повысит производительность.

если очистка данных невозможна, напишите пользовательскую функцию (UDF) для удаления начальных нулей, например

select * from table1 where dbo.udfStripLeadingZeros(table1.ID) = '1234'

это может не улучшить производительность (так как функцию придется запускать для каждой строки), но это устранит ложные совпадения и сделает цель запроса более очевидной.

Обновлено: предложение Тома H о преобразовании в целое число было бы лучше всего, если это возможно.

вроде не гарантирует сканирование таблицы, как "% 1234" - это сканирование таблицы. например, «1234%» - это не сканирование таблицы, при условии, что столбец проиндексирован, он будет использовать индекс для поиска 1234 ...

JoshBerke 19.12.2008 18:56

@ Джош: я сказал «сканирование индекса», а не «сканирование таблицы».

Steven A. Lowe 19.12.2008 20:30

@ Стивен: да, я не понимаю, почему, но когда я прочитал это в первый раз, я мог бы поклясться, что там сказано: таблица ... Я старею, я думаю ;-)

JoshBerke 21.12.2008 21:11

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

JoshBerke 21.12.2008 21:12

Если идентификатор является чисто числовым (как ваш пример), я бы рекомендовал (если возможно) заменить это поле на числовой тип. Если база данных уже используется, изменить тип может быть сложно.

Да, я не могу изменить исходную таблицу.

Sam Schutte 19.12.2008 23:00

Вы хотите убедиться, что хотя бы одна из таблиц использует свой фактический тип данных для идентификаторов и что она может использовать поиск по индексу, если это возможно. Это зависит от избирательности вашего запроса и количества совпадений, чтобы определить, какой из них следует преобразовать в другой. Если вы знаете, что вам нужно просмотреть всю первую таблицу, вы все равно не можете использовать поиск и вам следует преобразовать этот идентификатор в тип данных другой таблицы.

Чтобы убедиться, что вы можете использовать индексы, также избегайте LIKE. Например, гораздо лучше иметь:

WHERE
     T1.ID = CAST(T2.ID AS VARCHAR) OR
     T1.ID = RIGHT('0000000000' + CAST(T2.ID AS VARCHAR), 10)

чем:

WHERE
     T1.ID LIKE '%' + CAST(T2.ID AS VARCHAR)

Как заметил Стивен А. Лоу, второй запрос тоже может быть неточным.

Если вы собираетесь использовать все строки из T1 (другими словами, LEFT OUTER JOIN to T2), вам может быть лучше:

WHERE
     CAST(T1.ID AS INT) = T2.ID

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

Абсолютно лучший путь, как предлагали другие, - изменить тип данных таблиц, чтобы он соответствовал, если это вообще возможно. Даже если вы не можете сделать это до истечения срока реализации этого проекта, внесите его в свой список дел на ближайшее время.

Вы можете добавить в таблицу вычисляемый столбец. Затем проиндексируйте вычисляемый столбец и используйте этот столбец в соединении.

Бывший:

Alter Table Table1 Add PaddedId As Right('000000000000' + Id, 12)
Create Index idx_WhateverIndexNameYouWant On Table1(PaddedId)

Тогда ваш запрос будет ...

select * from table1 where table1.PaddedID ='000000001234'

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

Хорошо. Никаких OR, UDF в строке, индексируемых и т. д.

gbn 19.12.2008 18:42

Просто имейте в виду, что это вызовет (надеюсь, незначительное) попадание в вставки и обновления. Хорошая идея, если это не проблема.

Tom H 19.12.2008 20:12

если вы не можете исправить данные, чтобы они были согласованными, это следующее лучшее решение

Steven A. Lowe 19.12.2008 21:34

Как насчет,

table1WithZero.ID = REPLICATE('0', 12-len(table2.ID))+table2.ID

В этом случае он должен иметь возможность использовать индекс в таблице1

Ответ принят как подходящий

SQL Server выполняет короткое замыкание НЕТ, если условия. это невозможно, поскольку это система, основанная на затратах: Как SQL Server закорачивает оценку условия WHERE.

На всякий случай это полезно, как объясняет связанная страница в ответе Младена Прайдича, при оценке короткого замыкания находятся в разделе CASE.

Другие вопросы по теме