MYSQL — Условный столбец (если строка существует) в противном случае по умолчанию возвращается первым

#mysql

#mysql

Вопрос:

Я уверен, что это нетрадиционно, однако я пытаюсь выполнить следующее:

У меня есть следующая таблица:

 products_id, company_id, products_name
1,           1,          shoes
1,           2,          mens shoes
2,           1,          pants
  

Теперь, что я хочу сделать, это выбрать конкретное products_name из этого, используя заданный products_id и company_id = ‘2’, однако во всех случаях, когда он не находит строку с company_id = ‘2’, я хочу, чтобы по умолчанию он давал мне products_name для того же product_id с ЛЮБЫМ company_id .

Например, если бы я искал products_id = ‘2’, company_id = ‘2’, он должен вернуть products_name = ‘pants’ . Однако, если бы я искал products_id = ‘1’, company_id = ‘2’, он должен вернуть ‘мужская обувь’. Если бы я искал products_id = ‘3’, company_id = что угодно — он должен вернуть пустой набор.

Мне нужно иметь возможность сделать это в одном операторе SQL, поэтому никакой обработки через PHP для подтверждения того, существует ли строка, скажем: products_id = ‘2’ company_id = ‘2’.

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

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

1. Запуск скрипта для всех, кто хочет поиграть с ним: sqlize.com/cS21282NZw

Ответ №1:

Вот запрос, который вернет продукт компании или любой общий, если для этой компании нет конкретного продукта, по всему списку продуктов. Его можно легко отфильтровать с добавлением where products_id = ## в конце (или путем установки where фильтра внутри двух внутренних подзапросов, которые на самом деле могут быть более эффективными):

 set @company_id = 2;

select
    coalesce(p2.products_id, p1.products_id) as products_id,
    coalesce(p2.products_name, p1.products_name) as products_name
from
    (select products_id, max(products_name) as products_name
        from products group by products_id) p1
left join
    (select products_id, products_name
        from products where company_id = @company_id) p2
    on p1.products_id = p2.products_id
  

Демонстрация: http://sqlize.com/pkt568O0b5

Основная идея моей логики заключалась в следующем:

  1. Создайте запрос, который вводит произвольное название продукта для каждого идентификатора продукта — просто извлекая название max продукта и группируя по идентификатору.
  2. Создайте запрос, который извлекает название продукта для фильтруемой компании.
  3. Осталось соединить # 2 с # 1, чтобы у меня был список продуктов, а также название продукта для компании, если оно доступно. Из-за левого соединения все продукты все равно будут возвращены, но для продуктов, у которых нет определенного названия для данной компании, будет список для конкретной компании NULL .
  4. Выберите идентификатор продукта и название из данного списка для конкретной компании, если таковые имеются. Если недоступно, используйте общий список, который просто извлекает max название продукта. Это обрабатывается с помощью coalesce функции, которая возвращает первый ненулевой аргумент в своем списке. Таким образом, в основном сначала проверяется список, относящийся к конкретной компании, и, если ничего не доступно, вместо этого используется общий список.

Надеюсь, это поможет!

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

1. Эй, большое спасибо за такой исчерпывающий ответ, после написания я подумал, что если я присоединю таблицу к самой себе, я, вероятно, буду на правильном пути, но эта функция объединения — недостающая часть! Теперь я перейду к кодированию этого в свой скрипт. Еще раз, большое вам спасибо, это действительно ценится.