Что мне нужно выбрать в предложении WHERE EXIST?

Что мне нужно SELECT в подзапросе предложения WHERE EXIST?

Вот случайный запрос с предложением WHERE EXIST:

SELECT a.*
FROM a
WHERE EXISTS
(SELECT *
 FROM b
 WHERE  b.a_id = a.id)

Итак, * выбран в b. Но для меня это не имеет смысла, потому что я не хочу ничего выбирать (если только я не понял поведение WHERE EXIST). Я мог бы выбрать 1, но это тоже кажется странным.

Я думаю, что это не имеет особого значения с точки зрения скорости выполнения, и все могло бы сработать, но это может иметь значение с точки зрения удобочитаемости и «семантики». (Я не уверен в словах, которые использую!). Есть ли лучшая практика для этого? Если да, то почему один путь предпочтительнее другого?


person rap-2-h    schedule 30.03.2018    source источник
comment
Я всегда использую WHERE EXISTS (ВЫБЕРИТЕ 1 ИЗ ....)   -  person TheOni    schedule 30.03.2018
comment
Спасибо! Он не отвечает на вопрос, почему этот способ лучше другого? хотя. Скажем, почему бы и нет *?   -  person rap-2-h    schedule 30.03.2018
comment
В современных базах данных это не имеет особого значения, поскольку вы только проверяете их существование. 20 лет назад Oracle создавала бы более эффективные планы выполнения, если бы вы использовали SELECT 1, в то время как SQL Server понял бы, что нет необходимости выбирать какие-либо столбцы и создавать такой же план выполнения.   -  person Panagiotis Kanavos    schedule 30.03.2018
comment
@ rap-2-h ответ за последние 15 лет - это не имеет значения, если вы не заметите разницу. Если да, то это ошибка   -  person Panagiotis Kanavos    schedule 30.03.2018
comment
На это есть ответы на столько других вопросов и статей, что я не могу не задаться вопросом, приложили ли вы какие-либо усилия, чтобы найти ответ самостоятельно?   -  person MatBailie    schedule 30.03.2018
comment
В Postgres это можно полностью не указывать. SELECT без чего-либо в списке выбора действителен   -  person a_horse_with_no_name    schedule 30.07.2020


Ответы (2)


Неважно. Хорошей практикой является использование SELECT 1, чтобы указать, что это подзапрос, не возвращающий данные.

Выбор не оценивается и не имеет значения. В SQL Server вы можете поместить SELECT 1/0 в подзапрос exists, и он не приведет к ошибке деления на ноль даже.

По теме: Что легче читать в подзапросах EXISTS? https://dba.stackexchange.com/questions/159413/exists-select-1-vs-exists-select-one-or-the-other

Для неверующих:

 DECLARE @table1 TABLE (id INT)
 DECLARE @table2 TABLE (id INT)

 INSERT INTO @table1
 VALUES
 (1),
 (2),
 (3),
 (4),
 (5)

 
 INSERT INTO @table2
 VALUES
 (1),
 (2),
 (3)

SELECT * 
FROM @table1 t1
WHERE EXISTS (
SELECT 1/0
FROM @table2 t2
WHERE t1.id = t2.id)
person dfundako    schedule 30.03.2018
comment
Спасибо +1! В SQL Server вы можете поместить SELECT 1/0 в существующий подзапрос, и он даже не приведет к ошибке деления на ноль. - ›Интересный факт! Я только что попробовал это в postgreSQL, и он тоже работает! - person rap-2-h; 30.03.2018
comment
@ rap-2-h Делать 1/0 весело, и это действительно пугает людей во время проверки качества / проверки кода. Наблюдайте, как они тратят часы, пытаясь понять, почему это не ошибка. - person dfundako; 30.03.2018
comment
@dfundako, если они сходят с ума, пора отправить их на курс производительности SQL - person Panagiotis Kanavos; 30.03.2018
comment
Я просто пробовал select 1/0 и select 1/0 from FooTable в SSMS 17.6. Оба запроса привели к Divide by zero error encountered. - person ; 30.03.2018
comment
@ Hosch250 Выбор в EXISTS не оценивает. Выбор снаружи делает. - person dfundako; 30.03.2018
comment
uses less bytes to the engine since 1 is a bit and * is not. это полная чушь. Что ты имеешь в виду? - person joop; 30.03.2018
comment
@joop Ничего. Я сказал, что слышал это, и не стал вдаваться в подробности. Мне нечего подкрепить. - person dfundako; 30.03.2018
comment
@dfundako SELECT 1/0 - это мило, но я надеюсь, что вы не действительно заставляете людей тратить на это время, по крайней мере, не в профессиональной среде. - person 404; 31.03.2018
comment
@ 404: В Postgres вы можете заставить их тратить еще больше времени, используя пустой список выбора exist (select from ...);) - person a_horse_with_no_name; 30.07.2020

нотация * работает даже для таблицы без столбцов. (* не дороже 1; парсер понимает, что результаты подзапроса не нужны, аналогично COUNT(*))


CREATE TABLE none( none INTEGER ); -- ONE column
INSERT INTO none(none) SELECT 1 ; -- ONE row

ALTER  TABLE none
        DROP COLUMN none; -- NO columns!!!!

SELECT * FROM none; -- Still one row ...
SELECT COUNT(*) FROM none; -- Still one row ...

SELECT 'Yes'
WHERE EXISTS (
        SELECT *  -- even works for NO columns ...
        from none
        );
person joop    schedule 30.03.2018
comment
как получить строку из таблицы без столбцов? - person Malachi; 30.03.2018
comment
Еще есть строка, просто нет столбцов. * расширяется до нуля (пустой набор всех столбцов, но все еще действительный набор) и EXISTS(...) возвращает True, потому что что-то действительно существует; что-то без всяких столбцов ... - person joop; 30.03.2018
comment
кажется довольно нелогичным, это интересная ситуация, есть данные, где данных не должно быть, но они существуют. очень интересно - person Malachi; 30.03.2018
comment
На самом деле это очень логично. Таблица без каких-либо строк остается таблицей; почему строка без столбцов не должна оставаться строкой? Также: он делает ALTER TABLE DDL более регулярным: вы можете удалить столбец, даже если это единственный столбец. - person joop; 30.03.2018
comment
Впоследствии не нужно отбрасывать столбец: create table none(); insert into none default values; также будет работать - person a_horse_with_no_name; 30.07.2020