В настоящее время застрял на контрольно-пропускном пункте SQL, и мне не удается найти какие-либо ответы на мою проблему из-за того, насколько общими являются соответствующие слова.
У меня есть два запроса, которые кажутся одинаковыми, но дают разные результаты.
Для этих примеров предположим, что записи с id 123
НЕТ, а MyTable
имеет следующие столбцы: id
, time
и data
.
Один запрос для записи, которая не существует со всеми столбцами
SELECT id, data, time FROM MyTable WHERE id = 123
который не возвращает никаких результатов.
Другой запрос также относится к записи, которая не существует со всеми столбцами.
SELECT id, data, min(time) FROM MyTable WHERE id = 123
который возвращает один результат, где каждый столбец имеет значение null
Пример этого сценария из Android Studio:
не возвращает никаких результатов, как хотелось бы
возвращает один результат со всеми столбцами как null
такая же проблема возникает, даже если я называю столбец с тем же именем
Я пытаюсь добиться того же поведения во втором запросе, что и в первом; если результатов нет, то не возвращайте никаких результатов вместо того, чтобы возвращать один результат со всеми столбцами с нулевыми значениями.
Я понимаю, что могу обойти это, выполнив подзапрос и запросив его, но я бы предпочел использовать один запрос, такой же простой, как приведенные выше.
Это невозможно или есть способ добиться этого в Android Room Library/SQLite?
Обновлено: вопрос изначально был неверным, благодаря пользователям в комментариях я понял, что проблема возникает всякий раз, когда в запросе используется min(...)
, поэтому я обновил вопрос, чтобы отразить правильную проблему.
Что вы подразумеваете под: ... возвращает один результат, где каждый столбец имеет значение null? Если id=123 отсутствует, то оба запроса не возвращают никаких результатов.
Я предполагаю, что OP запрашивает с другим контекстом, чем запрос обычной таблицы, но функция с табличным значением, которая, вероятно, каким-то образом приводит к строке нулей... самый простой способ обойти это - добавить нулевую проверку в предложение where, чтобы отфильтровать нарушение ряд, напр. coalesce(id,time,data) is not null
но это основано только на предположении... было бы полезно, если бы OP прояснил вопрос
@forpas Я имею в виду, что когда я запрашиваю указанные столбцы, результат возвращает объект со всеми полями, для которых установлено значение null, но если я использую *, он не возвращает результатов
@DarkSquirrel42 Не знаю, как я могу пояснить, но я по крайней мере включу несколько примеров из моего варианта использования и скриншоты.
... результат возвращает объект со всеми полями, для которых установлено значение null, это невозможно, если нет id=123. Можете ли вы воспроизвести это с примерами данных в скрипке ?
@forpas Я полагаю, что на самом деле могу неправильно понять запрос, проблема возникает только в том случае, если в запрос включен минимум (столбец), например: SELECT id, min(time) FROM MyTable WHERE id = 123
. Я обновлю вопрос, чтобы отразить это правильно.
Я обновил вопрос, указав фактический случай, приношу извинения за неправильное толкование фактической причины, я не осознавал, что это ограничивается использованием min(...)
.
@forpas Боюсь, я не знаю, как использовать этот веб-сайт, чтобы привести скрипку в качестве примера моей ситуации.
Этот:
SELECT id, data, min(time) FROM MyTable WHERE id = 123
является агрегированным запросом без предложения GROUP BY, и поэтому он всегда возвращает ровно 1 строку.
Если вы хотите, чтобы он ничего не возвращал в случае невыполнения условия в предложении WHERE
, используйте EXCEPT
:
SELECT id, data, min(time) FROM MyTable WHERE id = 123
EXCEPT
SELECT null, null, null; -- as many null columns as the main selection
или используйте нестандартную функцию SQL SQL с предложением HAVING
в агрегированном запросе без предложения GROUP BY
(что не будет работать в других базах данных):
SELECT id, data, min(time) FROM MyTable WHERE id = 123
HAVING id IS NOT NULL;
или, с оговоркой GROUP BY
:
SELECT id, data, min(time) FROM MyTable WHERE id = 123
GROUP BY id
HAVING id IS NOT NULL;
Смотрите демо.
Это сработало отлично, и я могу жить с этим компромиссом. Если у кого-то еще нет лучшего способа сделать это, учитывая комментарии к моему вопросу, то это ответ, который я выбрал для своей проблемы. Также сегодня я узнал кое-что новое, так что спасибо за объяснение, почему это происходит.
@Shadow проверьте альтернативное решение в моем отредактированном ответе, который, как я уже упоминал, нестандартен и работает только в SQLite.
к сожалению, HAVING
не принимается в запросе Android Studio и библиотеке комнат, так что для меня это не вариант. Было бы здорово просто использовать этот единственный столбец вместо того, чтобы записывать их все в except select ...
.
так что кажется, что HAVING
можно использовать, но он ДОЛЖЕН сопровождаться GROUP BY...
в соответствии с их документацией developer.android.com/reference/android/arch/persistence/db/…
@Shadow, вы можете добавить предложение GROUP BY, не затрагивая функциональность этого запроса: SELECT id, data, min(time) FROM MyTable WHERE id = 123 GROUP BY id HAVING id IS NOT NULL;
: dbfiddle.uk/xwzRUphx
Готово, идеально! Можете ли вы обновить свой ответ этим? Я уверен, что другие, ищущие это, сочтут это наиболее полезным.
Чтобы вернуть что-либо, кроме одного значения, функция, связанная с запросом, должна вернуть объект. Результаты могут зависеть от возвращаемых объектов. Поэтому вам следует отредактировать свой вопрос, включив в него функции, связанные с запросами и соответствующими возвращаемыми объектами.