Я работаю над 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?
Вы ищете функцию 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)
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().
Используйте комбинацию 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
.
Взгляните на 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
Я не тестировал это, но вот как он должен работать в основном.
COALESCE
является стандартом ANSI и может использоваться в различных базах данных. Как вы упомянули,COALESCE
также может принимать более двух параметров. Большинство рекомендует использовать синтаксис ANSI всякий раз, когда это возможно.