Как фильтровать запрос с параметром, только если он передан?

Я не хочу писать два таких заявления

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

как я могу это сделать?

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

Schwern 08.08.2024 22:05

Действительно ли company_id является первичным ключом clients и именем клиента?

Schwern 08.08.2024 22:24
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

попробуй это

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?

Adrian Klaver 08.08.2024 22:04

@AdrianKlaver :filter_by_company — это логический параметр (0 — ложь, 1 — правда).

delfincortesb 08.08.2024 22:10
select 0 =0; t а это значит, что :filter_by_company = 0 выберет все. Приведите рабочий пример того, что вы предлагаете.
Adrian Klaver 08.08.2024 22:17

@AdrianKlaver: Да, в этом вся суть. Выберите все, если нет фильтрации по компании.

Ry- 08.08.2024 22:24

@Ry-, да, я перевернул логику в своей голове, моя ошибка.

Adrian Klaver 08.08.2024 22:27

Предполагая, что вы передаете 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 работает намного лучше, хотя требует больше кода.

The Impaler 08.08.2024 22:55

Я очень сомневаюсь, что короткое замыкание NULL IS NULL проверки приведет к какому-либо существенному влиянию на производительность.

ruohola 09.08.2024 10:47

Ответ правильный, но он создаст неоптимальный план, и это может заинтересовать ОП. Если NULL IS NULL жестко запрограммировано в буквальном виде, я бы с вами согласился. Однако если выражение параметризовано как ? IS NULL, то это совершенно другое животное.

The Impaler 11.08.2024 05:04
Ответ принят как подходящий

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

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)

Frank Heikens 08.08.2024 22:37

@FrankHeikens Смотри мой ответ..

ruohola 09.08.2024 21:37

Другие вопросы по теме