PostgreSQL. Следовательно, выберите результаты в соответствии с определенными фильтрами

#sql #postgresql #where-clause #psql

#sql #postgresql #где-предложение #psql

Вопрос:

У меня есть таблица с пользователями.

Пользователь (который использует эту программу) может выбирать пользователей, применяя различные фильтры. Фильтры A должны применяться немедленно, чтобы сократить время поиска в final SELECT и не тратить время впустую.

В настоящее время мой код выглядит следующим образом (Python, не уверен, что это работает, еще не протестирован).

Вопрос:

  1. Как применить фильтры сразу же, как только я получу пользовательский ввод?
  2. Как поместить / передать все действия, связанные с фильтрацией, в БД?
 if only_with_photo:
    cursor.execute('SELECT tg_user_id FROM suers WHERE photo IS NOT NULL')
    users_with_photo = cursor.fetchall()
if only_with_country:
    cursor.execute('SELECT tg_user_id FROM suers WHERE country IS NOT NULL')
    users_with_country = cursor.fetchall()
if only_with_city:
    cursor.execute('SELECT tg_user_id FROM suers WHERE city IS NOT NULL')
    users_with_city = cursor.fetchall()
    
    cursor.execute('SELECT tg_user_id FROM users WHERE tg_user_id IN (users_with_photo) AND tg_user_id                              IN (users_with_country ) AND tg_user_id IN (users_with_city) )
 

Задачи: выполнить эти запросы внутри psql без использования Python или другого языка?

Я пытался:

  1. КЕЙС sql = 'SELECT (CASE only_with_photo = 1 THEN (SELECT tg_user_id FROM users WHERE country IS NOT NULL)' --Subrequest returns more that one result
  2. Переменные /set only_with_photo := (SELECT tg_user_id FROM users WHERE birthdate IS NOT NULL); --Syntax just now working

Ответ №1:

Вы можете написать свой запрос с гибким предикатом и поместить его в процедуру с параметрами для каждого случая, например, следующими:

 SELECT tg_user_id 
FROM users 
WHERE (only_with_photo = 1 AND photo IS NOT NULL)
    OR (only_with_county = 1 AND county IS NOT NULL)
    OR (only_with_city = 1 AND city IS NOT NULL)
 

И т.д. Но это не обязательно самый эффективный способ сделать что-то, хотя это может быть достаточно хорошо для вашего случая. Вероятно, вы захотите добавить несколько индексов в таблицу users на основе нескольких наиболее вероятных комбинаций вышеуказанных предикатов.

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

1. Ваша логика, похоже, перевернута. Может быть, вы хотите WHERE (allow_without_photo > 0 OR photo IS NOT NULL) AND (...) ... И: да, это наиболее эффективный; оптимизатор распознает постоянные члены и применяет логику короткого замыкания)

2. @wildplasser Если вопрос не был обновлен с тех пор, я, должно быть, пропустил его последнюю строку в Python с совместным предикатом, когда я изначально писал это. Это позволит объединить только первые несколько запросов, а для последней части требуется дополнительная или совершенно другая фильтрация. Я соответствующим образом обновлю свой запрос, спасибо. Конечно, различная обработка данных может привести к более эффективному решению, но да, если это не вариант, такой запрос, вероятно, является лучшим, который можно получить с точки зрения производительности.

Ответ №2:

Это слишком долго для комментария.

[…] применяя различные фильтры. Фильтр должен быть применен немедленно, чтобы сократить время поиска при окончательном выборе и не тратить время впустую.

Это не так, как работает SQL. Это язык, основанный на множествах, где, как только результат был описан клиентом, все операции выполняются базой данных сразу, так, как она считает наиболее эффективным.

Язык не предлагает возможности интерактивного уточнения результирующего набора. Итак, то, что вы запрашиваете, потребует создания такой функции, возможно, путем создания временной таблицы для каждой таблицы, подачи в нее результатов первого поиска, а затем удаления строк при уточнении критериев.

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