Как выполнить EXISTS select в ANSI SQL

#sql #ansi-sql

#sql #ansi-sql

Вопрос:

Существует ли кросс-база данных (по крайней мере, SQL Server, Oracle, Postgre, MySQL, SQLite) способ сделать то, что я бы сделал в T-SQL, используя

 SELECT 1 WHERE EXISTS (SELECT * FROM Foo WHERE Bar = 'Quux')
  

Кажется, что это недопустимый синтаксис ANSI SQL, потому что в нем нет предложения FROM . В настоящее время я использую COUNT (*) для этого, но я не думаю, что это оптимально.

Ответ №1:

Подзапрос не нужен — используйте:

 SELECT DISTINCT 
       1 
  FROM Foo 
 WHERE Bar = 'Quux'
  

Более сложная версия, использующая агрегаты и выражение CASE:

 SELECT CASE
         WHEN COUNT(*) >= 1 THEN 1 
         ELSE 0
       END
  FROM Foo 
 WHERE Bar = 'Quux'
  

Комментарии:

1. Интересно, почему бы не использовать limit вместо distinct? Разве это не совместимо с ABSI? ВЫБЕРИТЕ 1 Из Foo, ГДЕ Bar = ‘Quux’ LIMIT 1;

2. @andrii К сожалению, LIMIT не совместим с ANSI. Начиная с SQL2008, у нас есть преимущество «ВЫБОРКИ ТОЛЬКО ПЕРВЫХ n СТРОК» и оконных агрегатных функций, но их поддерживают только несколько ядер баз данных. Также LIMIT сильно отличается от DISTINCT. Мы знаем, что здесь все кортежи у нас одинаковые, следовательно, возвращаем результат в одну строку с DISTINCT. Здесь нет необходимости искусственно прерывать результирующий набор.

Ответ №2:

Немного обманываю, но это должно сработать, и DISTINCT 1 FROM Foo должно быть тривиально оптимизировано всеми, кроме самой тупой из СУБД!

SELECT DISTINCT 1 FROM Foo WHERE EXISTS (SELECT * FROM Foo WHERE Bar = 'Quux')

Ответ №3:

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

 SELECT COUNT(Bar) FROM Foo WHERE Bar = 'Quux'
  

Конечно, вы обменяете оптимизацию на переносимость, поэтому в этом случае используйте COUNT

Комментарии:

1. Я работаю над библиотекой общего назначения, поэтому мне нужно наилучшее сочетание оптимального и переносимого. И печенье! 🙂