Я не хочу писать два таких заявления
if (filter_by_company) {
query..
} else {
query...
}
Итак, выберите пользователей, и они входят в компании, и я, администратор, могу фильтровать их по идентификатору компании. Как я могу сказать, что если фильтр не существует, то не создавать условие?
SELECT * FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
WHERE c.company_id = 'NAME' IF EXISTS ?? ELSE DONT ASK
как я могу это сделать?
Действительно ли company_id
является первичным ключом clients
и именем клиента?
попробуй это
SELECT * FROM users u
LEFT JOIN clients c ON c.id = u.company_id
WHERE (:filter_by_company = 0 OR c.company_id = :company_id)
Как именно это ответ? Что должен обозначать :filter_by_company
?
@AdrianKlaver :filter_by_company — это логический параметр (0 — ложь, 1 — правда).
select 0 =0; t
а это значит, что :filter_by_company = 0
выберет все. Приведите рабочий пример того, что вы предлагаете.
@AdrianKlaver: Да, в этом вся суть. Выберите все, если нет фильтрации по компании.
@Ry-, да, я перевернул логику в своей голове, моя ошибка.
Предполагая, что вы передаете company_id
как позиционный параметр, передайте его дважды подряд (передавайте null
на своем языке программирования, если вы этого не делаете filter_by_company
):
SELECT * FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
WHERE (? IS NULL OR c.company_id = ?);
Если ваш клиент разрешает именованные параметры, вы можете использовать:
SELECT * FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
WHERE (:company_id IS NULL OR c.company_id = :company_id);
или какой-либо другой эквивалентный синтаксис параметров.
Хотя это технически возможно, это приводит к снижению производительности SQL. Динамический SQL работает намного лучше, хотя требует больше кода.
Я очень сомневаюсь, что короткое замыкание NULL IS NULL
проверки приведет к какому-либо существенному влиянию на производительность.
Ответ правильный, но он создаст неоптимальный план, и это может заинтересовать ОП. Если NULL IS NULL
жестко запрограммировано в буквальном виде, я бы с вами согласился. Однако если выражение параметризовано как ? IS NULL
, то это совершенно другое животное.
Я думаю, вы спрашиваете, как написать один запрос, который может обрабатывать как фильтрацию по компании, так и не фильтрацию по компании.
SELECT *
FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
WHERE c.company_id = 'NAME'
и
SELECT *
FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
Есть два подхода. Во-первых, попытаться сконструировать это как один запрос. Второй — использовать более гибкий подход к построению запросов.
Чтобы сделать это в одном запросе, вам нужно передать логический флаг, чтобы определить, следует ли фильтровать по компании.
SELECT *
FROM users u
LEFT JOIN clients c
ON c.id = u.company_id
WHERE (:any_company or c.id = :company_id)
Демонстрация.
Это приемлемо для чего-то простого, но этот метод очень ограничен и приводит к излишне сложным запросам.
Гораздо лучше использовать построитель запросов SQL для построения запросов. Затем вы можете написать общий запрос и добавить в него предложения. То, что вы используете, зависит от вашего выбора языков программирования, для этих примеров мы будем использовать Knex.js.
Сначала создайте базовый запрос.
const user_client_query = knex
.select('*')
.from('users')
.leftJoin('clients', 'users.company_id', 'clients.id');
И дополняйте его по мере необходимости.
const filter_user_by_client = user_client_query.where('clients.company_id', 'ConHuge Corp')
filter_user_by_client
— новый объект, user_client_query
не затронут.
Прелесть этого метода в том, что вы можете добавлять ограничения, порядки, дополнительные предложения, дополнительные соединения и так далее.
user_client_query.orderBy('user.last_login').limit(10)
И он адаптируется за вас к диалектам SQL.
Вы также можете использовать (:company_id IS NULL or c.id = :company_id)
@FrankHeikens Смотри мой ответ..
Это было бы легче понять, если бы вы предоставили базовые схемы для пользователей и клиентов, примеры данных и ожидаемые результаты в двух разных ситуациях.