Выбрать столбец со значением по умолчанию или столбец с пользовательским значением, если не ноль?

0

Я работаю над webapp с набором данных, которые пользователи могут просматривать и редактировать.

Пользователи хотят настроить одно из полей, которые появляются для каждого элемента, например "product_name".

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

Таблица продуктов будет похожа на (пропуская синтаксис cruft, вы получите идею):

CREATE TABLE products (
  pid     int,            # product id
  pname   varchar         # product name (users want to customize this)
);

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

Для экономии пространства я подумал об использовании дополнительной таблицы, которая "переопределяет" значения по умолчанию для любого данного пользователя для любого данного продукта. Строки добавляются в эту таблицу по мере необходимости. Пользователь, который не настраивал имя какого-либо продукта, не имел бы никаких строк:

CREATE TABLE custom (
  pid     int,
  userid  int,
  pname   varchar
);

Я могу легко соединить эти две таблицы с идентификатором продукта и мог выбрать значение по умолчанию (product.pname) или отредактированное пользователем значение (custom.pname) для каждой строки в php, но я надеюсь, что есть больше эффективный способ сделать это в MySQL.

Есть ли выражение, которое позволяет мне выбрать один столбец, если не null, иначе выбрать другой (по двум таблицам)?

Вы предлагаете другой способ справиться с этим?

Спасибо.

PS: может быть, тип JOIN, который позволит столбцу таблицы 2 с тем же именем переопределить столбец в таблице 1 для тех строк, где он существует в таблице 2?

Теги:
schema

4 ответа

1
Лучший ответ

Вы ищете функцию COALESCE.

SELECT COALESCE(the_field, "This literal") FROM YOUR_TABLE

приводит к полю the_field, если поле the_field не равно null, иначе это "этот литерал". Вы можете смешивать поля и литералы столько, сколько хотите.. поэтому SELECT COALESCE (this_field, that_field) работает тоже. У вас может быть более 2 параметров... например. SELECT COALESCE (this_field, that_field, theother_field)

  • 0
    Благодарю. Я нашел похожий оператор с именем IFNULL (). IFNULL (expr1, expr2) представляется эквивалентным COALESCE (expr1, expr2). Я не уверен, какой смысл использовать этот вариант, поскольку COALESCE () может принимать более двух аргументов.
  • 1
    @faB: IFNULL специфичен для MySQL; COALESCE является стандартом ANSI и может использоваться в различных базах данных. Как вы упомянули, COALESCE также может принимать более двух параметров. Большинство рекомендует использовать синтаксис ANSI всякий раз, когда это возможно.
2
select if(c.pname is not null, c.pname, p.pname) pname
  from products p left outer join custom c on c.pid = p.pid;

Левое внешнее соединение всегда выдает совпадение строк, которое будет иметь нулевые поля, если соединение завершится неудачно, вы можете проверить это с помощью функции if().

  • 0
    Ах, я думал, что должно быть что-то вроде троичного оператора. Будет интересно исследовать это и объединиться сейчас в справочном руководстве и посмотреть, как подходы различаются. Спасибо!
2

Используйте комбинацию LEFT JOIN и COALESCE:

   SELECT p.pid,
          COALESCE(c.pname, p.pname) AS product_name
     FROM PRODUCT p
LEFT JOIN CUSTOM c ON c.pid = p.pid
                  AND c.userid = ?

Поскольку c.pname будет null, если пользователь не предоставил собственное имя, функция COALESCE по умолчанию будет использовать следующее значение, отличное от NULL, - от p.pname.

1

Взгляните на MySQL CASE -statement. Это должно сделать трюк:

   SELECT CASE
              WHEN `custom`.`pname` IS NULL
              THEN `products`.`pname`
              ELSE `custom`.`pname`
          END CASE AS `pname`
     FROM `products`
LEFT JOIN `custom`
       ON `custom`.`pid` = `products`.`pid`
    WHERE `products`.`pid` = 123

Я не тестировал это, но вот как он должен работать в основном.

  • 0
    Спасибо, в любом случае, чтобы сделать это с простым запросом SELECT? Я еще не использовал «хранимую программу» (хранимую процедуру?) В этом приложении, и у меня пока нет фреймворка.
  • 0
    Посмотрите на мое дополнение.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню