IN vs БЕЗКОШТОВНИЙ оператор у PostgreSQL


119

У чому різниця між оператором INі ANYPostgreSQL?
Здається, механізм роботи обох однаковий. Хтось може пояснити це прикладом?


3
Можливий дублікат postgreSQL - in vs any
Vivek S.

Чи відповідає це на ваше запитання? Різниця між в і будь-яких операторів в SQL
philipxy

Відповіді:


158

(Ні, INні ANY"оператор". "Конструкція" або "елемент синтаксису".)

Логічно , цитуючи посібник :

INеквівалентно = ANY.

Але є два варіанти синтаксису з INі два варіанти ANY. Деталі:

IN взяти набір еквівалентно = ANYприйому набору , як показано тут:

Але другий варіант кожного не рівнозначний іншому. Другий варіант ANYконструкції займає масив (повинен бути фактичним типом масиву), тоді як другий варіант INмає перелік значень, розділених комами . Це призводить до різних обмежень у передачі значень, а також може призвести до різних планів запитів у особливих випадках:

ANY є більш універсальним

ANYКонструкція є набагато більш універсальним, так як він може бути об'єднаний з різними операторами, а не тільки =. Приклад:

SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');

Для великої кількості значень найкраще забезпечувати задану шкалу для кожного:

Пов'язані:

Інверсія / протилежність / виключення

"Знайти рядки, де idзнаходиться у даному масиві":

SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);

Інверсія: «Знайти рядки , в яких idє НЕ в масиві»:

SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('{1, 2}');  -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('{1, 2}'));

Усі три еквіваленти. Перший з конструктором масиву , інші два з літералом масиву . Тип даних може бути отриманий з контексту однозначно. В іншому випадку може знадобитися чіткий ролик, наприклад '{1,2}'::int[].

Рядки з id IS NULLне містять жодного з цих виразів. Щоб NULLдодатково включити значення:

SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;

4
Було б добре чітко уточнити, що результати другого варіанту завжди будуть однаковими. Я на 99% впевнений, що це насправді так, але відповідь, схоже, не говорить про це. Це означає, що SELECT * from mytable where id in (1, 2, 3)завжди буде мати однакові рядки SELECT * from mytable where id = ANY('{1, 2, 3}'), навіть якщо вони потенційно можуть мати різні плани запитів.
КПД

1
ANY не може поєднуватися з !=оператором. Я не думаю, що це документально підтверджено, але select * from foo where id != ANY (ARRAY[1, 2])це не те саме, що select * from foo where id NOT IN (1, 2). З іншого боку, select * from foo where NOT (id = ANY (ARRAY[1, 2]))працює як очікувалося.
qris

1
@qris: ANYможе поєднуватися з !=оператором. Але в цьому є більше. Я додав розділ вище. (Зауважте, що <>це оператор у стандартному SQL - хоча !=це прийнято також і в Postgres.)
Ервін

Як працює остання версія, що включає NULLзначення? Працювало б WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;так само добре?
двтан

1
@dvtan: (id = ...) IS NOT TRUEпрацює, тому що id = ...оцінює лише те, TRUEчи є фактична відповідність. Результати FALSEабо NULLпройти тест. Дивіться: stackoverflow.com/a/23767625/939860 . Ваш доданий тест на експресію на щось інше. Це було б рівнозначноWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Ервін Брандштеттер

3

Є два очевидних моменти, а також пункти в іншій відповіді:

  • Вони точно еквівалентні при використанні підзапитів:

    SELECT * FROM table
    WHERE column IN(subquery);
    
    SELECT * FROM table
    WHERE column = ANY(subquery);

З іншої сторони:

  • Тільки INоператор дозволяє простий список:

    SELECT * FROM table
    WHERE column IN(… ,  , …);

Якщо припустити, що вони абсолютно однакові, мене кілька разів зловило, забувши, що ANYне працює зі списками.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.