sqlite проверяет покрытие набора

#sql #sqlite

#sql #sqlite

Вопрос:

Может ли SQLite проверять установленное покрытие с помощью IN оператора?

ie (SELECT n from nums where n < 4) IN (1,2,3,4) (где nums — набор целых чисел) вернул бы true

Я искал документы, но могу найти только документы, в которых используется только одно значение слева от IN . Тесты показали, что это возможно, но мне нужно подтвердить, что это допустимый вариант использования, а не побочный эффект, подобный способности SQLite возвращать агрегированные запросы без соответствующих GROUP BY инструкций.

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

1. Что именно вы имеете в виду, говоря «это может»? Показанное вами выражение недопустимо ни в одной версии SQLite.

2. НЕТ . Проверяется наличие в наборе только одного значения . То есть: 2 IN (1, 2, 3, 4) вернул бы true .

3. @CL если вы запустите подзапрос, подобный этому, где num — это таблица целых чисел (выберите n из num, где n < 3) В (1,2,3,4), он вернет true. Но если вы запустите (выберите n из num, где n < 4) В (1,2,4), он вернет false, что является ожидаемым поведением. Прошу прощения, я пропустил введенный вопрос.

Ответ №1:

В документации сказано «нет».

Операторы IN и NOT IN принимают одиночный скалярный операнд слева и векторный операнд справа, образованный явным списком из нуля или более скаляров или одним подзапросом.

Акцент мой

https://www.sqlite.org/lang_expr.html#in_op

Ответ №2:

В документации говорится:

Операторы IN и NOT IN принимают один скалярный операнд слева

Поэтому, если вы используете подзапрос с левой стороны, он обрабатывается как скалярный подзапрос, который ведет себя не так, как вы хотите:

Результатом выражения является значение единственного столбца в первой строке, возвращаемое оператором SELECT. Если ВЫБОР выдает более одной результирующей строки, все строки после первой игнорируются.

Чтобы проверить покрытие набора, вы должны проверить, есть ли в левом наборе какой-либо элемент, которого нет в правом наборе:

 WITH a(n) AS (
  SELECT n
  FROM nums
  WHERE n < 4
),
b(n) AS (
  VALUES (1), (2), (3), (4)
)
SELECT *
FROM a
WHERE NOT EXISTS (SELECT 1
                  FROM b
                  WHERE b.n = a.n);