:: Не фоксом единым
SQL Server Узнать существует ли хотя бы одна запись
GotFocus
Автор

Сообщений: 1191
Откуда: Из-за угла
Дата регистрации: 30.11.2010
Раньше узнавал скалярным запросом
1.
SELECT COUNT(*) FROM table
WHERE ...
проверяя возвращаемое значение на неравенство 0

Теперь хочу ускорить -
2.IF EXISTS (SELECT COUNT(*) FROM table WHERE ...)
2.IF EXISTS (SELECT * FROM table WHERE ...)
Print 'Yes'
в SSMS работает. А как это вызвать в виде скалярного запроса ? Если подставить вместо 1. строку
EXISTS (SELECT * FROM table WHERE ...)
возвращающую bool, то возникает ошибка.

А может есть по-лучше способ определения наличия записи в таблице ?



Исправлено 2 раз(а). Последнее : GotFocus, 27.01.13 17:44
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
PaulWist

Сообщений: 14614
Дата регистрации: 01.04.2004
GotFocus
Раньше узнавал скалярным запросом
1.
SELECT COUNT(*) FROM table
WHERE ...
проверяя возвращаемое значение на неравенство 0

Теперь хочу ускорить -
2.
IF EXISTS (SELECT COUNT(*) FROM table WHERE ...)
Print 'Yes'
в SSMS работает. А как это вызвать в виде скалярного запроса ? Если подставить вместо 1. строку
EXISTS (SELECT COUNT(*) FROM table WHERE ...)
возвращающую bool, то возникает ошибка.

А может есть по-лучше способ определения наличия записи в таблице ?

1. Из прямого запроса никак только через select:

IF EXISTS (SELECT COUNT(*) FROM table WHERE ...)
select cast(1 as bit) Exists

2. из ХП через output параметр, см ФАК.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
1. Зачем тут count(*)?
2. В МЫ SQL нет булевого типа данных и вернуть его невозможно.
3. Как вариант возможного решения:
select case when exists(select * from spt_values) then '1' else '2' end


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Penner

Сообщений: 4102
Откуда: Muenster
Дата регистрации: 26.04.2002
select 1 as nn where EXISTS (SELECT * from Table)


------------------
Никогда не откладывайте на завтра, то, о чем можно забыть навсегда
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
GotFocus
Автор

Сообщений: 1191
Откуда: Из-за угла
Дата регистрации: 30.11.2010
ssa
1. Зачем тут count(*)?
Опечатка - исправил в 1-ом сообщении

Обязуюсь до конца следующей недели сравнить по скорости все 3 предложенных варианта(проверил - все работают) + вариант с ХП
1. select cast(1 as bit) where Exists(SELECT * FROM table WHERE ...)
2. select case when exists(select * from table WHERE ...) then '1' else '2' end
3. select 1 as nn where EXISTS (SELECT * from table WHERE ...)
и сообщить

Всем спасибо ! Если есть ещё варианты - предлагайте.
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
select top 1 * from ...
В зависимости от запроса это может оказаться не менее эффективно чем EXISTS.

Хотя, как всегда, встаёт вопрос - на кой нужно такое "знание". Если тебе нужны данные - ты и запрашивай САМИ данные (возможно принудительно ограничивая размер выборки, чтобы не тянуть 100500 записей) - а просто сам факт "ну там что-то есть"... Обычно он бесполезен "сам по себе" - т.е. всё равно последует запрос данных - а раз так, то зачем "лишний" запрос "а есть ли там данные"...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
PaulWist

Сообщений: 14614
Дата регистрации: 01.04.2004
Igor Korolyov
select top 1 * from ...
В зависимости от запроса это может оказаться не менее эффективно чем EXISTS.

Хотя, как всегда, встаёт вопрос - на кой нужно такое "знание". Если тебе нужны данные - ты и запрашивай САМИ данные (возможно принудительно ограничивая размер выборки, чтобы не тянуть 100500 записей) - а просто сам факт "ну там что-то есть"... Обычно он бесполезен "сам по себе" - т.е. всё равно последует запрос данных - а раз так, то зачем "лишний" запрос "а есть ли там данные"...

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


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
А при чём тут триггера? Триггера это T-SQL, и там нет проблем написать IF EXISTS (...) Речь то шла о том как из клиентского кода "это" получить
Впрочем, как часто нужно писать триггера для проверки RI, учитывая что MSSQL поддерживает декларативный RI, и даже с "каскадными" расширениями типа ON DELETE CASCADE...
IMHO это либо очень редкие исключения для сложных/нетривиальных структур данных, либо проектировщик БД которого нужно немедленно увольнять


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
GotFocus
Автор

Сообщений: 1191
Откуда: Из-за угла
Дата регистрации: 30.11.2010
Результаты тестирования по скорости
Использовал таблицу BigTable - около 8 млн записей - 4 столбца, один из них - column1 - float без ключей. В нём значения от 1 до 7500000. При создании таблицы в каждой добавляемой записи его значение увеличивалось на 1.

Думал, что буду сравнивать предложенные варианты. Да не тут-то было. Пришлось сравнивать 4 варианта(все они примерно одинаковые по скорости) с COUNT(*)

1. Рассматриваем записи начиная с 333. Как видим COUNT(*) отдыхает, потому что до искомых записей рукой подать
[attachment 15385 ÑíèìîêBB1.PNG]

2. Рассматриваем записи начиная с 4444444. Конечно COUNT(*) нашёл всего 86224 записей против 7835246 в 1. и поэтому быстрее(но всего лишь в два раза). Но что случилось с вариантами с EXISTS и с 4-ым ? Понятно, что скорость поиска записи должна была уменьшиться - ведь далеко от начала таблицы. Но почему выиграл COUNT(*) в 3 раза - непонятно
[attachment 15386 ÑíèìîêBB2.PNG]

Подумал, что может быть не использовать SELECT ... EXISTS, а использовать ХП, в которой будет что-то вроде if EXISTS (SELECT * FROM BigTable WHERE column1>4444444) - но в SSMS - те же 3 сек

Так что моя мечта, увидеть этакую COUNT_X, которая встретив первую удовлетворяющую условию запись бросает подсчёт и возвращает 1, пока не осуществилась

Неужели нет ничего, что будет всегда находить 1 запись быстрее COUNT(*) ?



Исправлено 1 раз(а). Последнее : GotFocus, 29.01.13 22:54
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
Оптимизация запросов - отдлельная большая тема. У запросов нет жестко зафиксированного вермени исполнения, план выполнения запроса может меняться в любое время в зависимости от кучи условий и потому твои попытки сравнить сферических коней, как и попытки найти абсолют, совершенно бессмыселенны.


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
GotFocus
[b]...
Неужели нет ничего, что будет всегда находить 1 запись быстрее COUNT(*) ?

select top 1 column1 from table where ...

Ну и если EXISTS, то именно покажет просто есть или нет.
IF EXISTS (SELECT top 1 column1 FROM table WHERE ...)
Print 'Yes'
Мне кажется, в общем случае, самый быстрый вариант. Т.к. ищется первая же подходящая запись, и все.
Может и ошибаюсь.


------------------




Исправлено 1 раз(а). Последнее : Аспид, 29.01.13 08:41
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
PaulWist

Сообщений: 14614
Дата регистрации: 01.04.2004
Igor Korolyov
...
Впрочем, как часто нужно писать триггера для проверки RI, учитывая что MSSQL поддерживает декларативный RI, и даже с "каскадными" расширениями типа ON DELETE CASCADE...
IMHO это либо очень редкие исключения для сложных/нетривиальных структур данных, либо проектировщик БД которого нужно немедленно увольнять

Хорошо, Игорь.

Теперь скажи какой "стандарный" RI (FK) навесить на пару "таблица" - "справочник", если надо создать запись в "таблице", PK справочника занести потом:

create table Dictionary (f1 int PRIMARY KEY )
create table [table] (f1 int FOREIGN KEY REFERENCES Dictionary (f1) )


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
PaulWist
Теперь скажи какой "стандарный" RI (FK) навесить на пару "таблица" - "справочник", если надо создать запись в "таблице", PK справочника занести потом:
Такой же как и в случае если сразу заполняется FK - только это поле должно дополнительно допускать NULL-ы (оно как раз и будет содержать NULL до момента заполнения). При этом я совершенно не вижу чем тут поможет самописный триггер - он точно так же должен проверять запись в момент её создания, а не "потом, когда будет заполняться поле FK, если оно вообще будет заполняться..." И куда как логичнее использовать в качестве "незаполненного значения" NULL - который корректно обрабатывается декларативным RI констрейном, чем какое-то "волшебное значение" осгобым образом обрабатываемое самописным RI триггером.
create table Ref (RefID int PRIMARY KEY, Name varchar(100));
create table Main (MainID int PRIMARY KEY, RefID int REFERENCES Ref(RefID), SomeData varchar(100));
insert into Main (MainID, SomeData) VALUES (1, 'пустой');
insert into Ref (RefID, Name) VALUES (100, 'справочная 100');
update Main set RefID = 100, SomeData = 'непустой' where MainID = 1;
insert into Main (MainID, RefId, SomeData) VALUES (2, 100, 'изначально непустой');
--Нижеуказанные команды не пройдут из-за ограничений RI
insert into Main (MainID, RefId, SomeData) VALUES (3, 101, 'некорректный');
update Main set RefID = 101 where MainID = 1;

2 GotFocus
Делать для огромной таблицы запрос с условием вида column1 op значение и НЕ делать при этом индекса по данному полю, конечно же можно... Но вот делать на основе этого какие либо далеко идущие выводы - совершенно бессмысленно. Точно так же не следует думать:
- что "физически" записи хранятся в том порядке в котором они создавались.
- что при выборке (без использования индексов) записи просматриваются в каком то определённом порядке (физическом, или логическом).
- что запрос SELECT TOP 1 * FROM table WHERE column1 > 123 вернёт запись у которой column1 будет минимальным из всех тех у которых значение > 123. Вообще с точки зрения формальной логики SQL-я запрос с TOP нуждается в опции ORDER BY - иначе его результат абсолютно непредсказуем.
А вот на что следовало бы обратить внимание, так это на планы исполнения соответствующих запросов - вероятнее всего все 4 "кандидата" имеют в своей основе один и тот же план (точнее самая "тяжелая" часть запроса - сканирование этой большой таблицы БЕЗ индекса НО до первого "нахождения" - будет идентичной, а вот мелочи связанные с "обвеской" каждого конкретного запроса будут различаться). Для COUNT(*), естественно, никакой "остановки при первом же нахождении" быть не может.
P.S. 1 и 3 варианты в принципе ничем не различаются.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
PaulWist

Сообщений: 14614
Дата регистрации: 01.04.2004
Igor Korolyov
PaulWist
Теперь скажи какой "стандарный" RI (FK) навесить на пару "таблица" - "справочник", если надо создать запись в "таблице", PK справочника занести потом:
Такой же как и в случае если сразу заполняется FK - только это поле должно дополнительно допускать NULL-ы .

Точно, совсем забыл с этими триггерами

Тем не менее, триггер RI тоже нужен, например когда надо выдать "человеческое" сообщение на клиента, минуя обработчик ошибок клиента.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
PaulWist
Тем не менее, триггер RI тоже нужен, например когда надо выдать "человеческое" сообщение на клиента, минуя обработчик ошибок клиента.
Сомневаюсь. Это уж скорее нужен набор CRUD процедур который "прячет" прямую работу с таблицей - и это совсем другая "тема". А триггере не должен, да и не может адекватно "озвучивать" ошибки (какую, кстати из "множества возникших" он должен озвучить для команды update Main set RefID = RefId+1 ?)... При том декларативный RI наверняка и работает быстрее чем сходный RI триггер.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
PaulWist

Сообщений: 14614
Дата регистрации: 01.04.2004
Igor Korolyov
PaulWist
Тем не менее, триггер RI тоже нужен, например когда надо выдать "человеческое" сообщение на клиента, минуя обработчик ошибок клиента.
Сомневаюсь. Это уж скорее нужен набор CRUD процедур который "прячет" прямую работу с таблицей - и это совсем другая "тема". А триггере не должен, да и не может адекватно "озвучивать" ошибки (какую, кстати из "множества возникших" он должен озвучить для команды update Main set RefID = RefId+1 ?)... При том декларативный RI наверняка и работает быстрее чем сходный RI триггер.

Если триггер написан для проверки RI конкретного PK (понятно, что триггер должен быть FOR DELETE-UPDATE-INSERT), то именно эту ошибку он должен вернуть, другие PK проверяются другими триггерами, исключением может быть только ошибки среды выполнения, но их должены ловить либо ХП сервера, либо клиент.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
LED

Сообщений: 204
Дата регистрации: 22.07.2006
Подскажите как решить вот такую как бы можно сказать задачу...

Dtp – дата
okID - номер

Ищем наименьшую и наибольшую дату получения товара по его номеру
SELECT Min(dtp),Max(dtp) FROM _nfile WHERE okID=okID1



Получаем 2 поля:
Min_dtp и Max_dtp

Если товара в базе нет получаем .ISNULL. в этих полях



Чтобы избавиться от .ISNULL.
Создал вот такую конструкцию:
SELECT Min(dtp),Max(dtp) WHERE NOT EXISTS (SELECT * FROM _nfile WHERE okID=okID1)
Не получается, появляется окно с предупреждением, что неправильное выражение.
Подскажите как избавиться от .ISNULL.
Т.е. надо создать такой запрос, чтобы при получении .ISNULL. можно было
Вывести, что нет такого номера товара в базе (нет такого товара)
Применил EXISTS для обнаружения .ISNULL. но почему то не получается.

Как составить запрос?
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
ВладимирС

Сообщений: 1693
Дата регистрации: 03.11.2005
LED
Подскажите как решить вот такую как бы можно сказать задачу...
Dtp – дата
okID - номер

Ищем наименьшую и наибольшую дату получения товара по его номеру
SELECT Min(dtp),Max(dtp) FROM _nfile WHERE okID=okID1



Получаем 2 поля:
Min_dtp и Max_dtp

Если товара в базе нет получаем .ISNULL. в этих полях



Чтобы избавиться от .ISNULL.
Создал вот такую конструкцию:
SELECT Min(dtp),Max(dtp) WHERE NOT EXISTS (SELECT * FROM _nfile WHERE okID=okID1)
Не получается, появляется окно с предупреждением, что неправильное выражение.
Подскажите как избавиться от .ISNULL.
Т.е. надо создать такой запрос, чтобы при получении .ISNULL. можно было
Вывести, что нет такого номера товара в базе (нет такого товара)
Применил EXISTS для обнаружения .ISNULL. но почему то не получается.

Как составить запрос?
Так подойдет ?
SELECT ISNULL(Min(dtp),0),ISNULL(Max(dtp),0) FROM _nfile WHERE okID=okID1
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
LED

Сообщений: 204
Дата регистрации: 22.07.2006
SELECT ISNULL(Min(dtp),0),ISNULL(Max(dtp),0) FROM _nfile WHERE okID=okID1
Не работает. Пишет ошибку



Исправлено 1 раз(а). Последнее : LED, 27.10.16 09:23
Ratings: 0 negative/0 positive
Re: SQL Server Узнать существует ли хотя бы одна запись
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Человек синтаксис MS привел.
В фоксе NVL
SELECT NVL(Min(dtp),0),NVL(Max(dtp),0) FROM _nfile WHERE okID=okID1
И не плохо б приводить текст ошибки. А заодно и читать.
Из нее все понятно будет.

Но не думаю что сама идея такого запроса верна.
Потому как вернет запись все равно, просто вместо поля date будет int

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


------------------




Исправлено 2 раз(а). Последнее : Аспид, 27.10.16 09:51
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 4 (Гостей: 4)

© 2000-2024 Fox Club 
Яндекс.Метрика