我正在开发一个带有一组用户可以浏览和编辑的数据的webapp。
用户希望自定义每个项目显示的字段之一,例如“product_name”。
每个产品在表格中都有一组默认值,对所有用户都是相同的:
产品表就像(跳过语法残留,你明白了):
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
);
我可以轻松地在产品ID上加入这两个表,并且可以为php中的每一行选择默认(products.pname)或用户编辑的值(custom.pname),但我希望还有更多在MySQL中执行此操作的有效方法。
是否有一个表达式允许我选择一列,如果不是null,否则选择另一列(跨两个表)?
你会建议采用不同的方法来处理这个问题吗?
谢谢。
PS:也许是一种JOIN类型,它允许表2的一列具有相同的名称,以覆盖表1中列表中存在的那些行?
答案 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
。< / p>
答案 1 :(得分: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()函数测试它。
答案 2 :(得分: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
我没有对此进行测试,但这基本上应该是如何工作的。
答案 3 :(得分:1)
您正在寻找COALESCE功能。
SELECT COALESCE(the_field, "This literal") FROM YOUR_TABLE
如果the_field不为null,则导致the_field,否则为“This literal”。你可以根据需要混合字段和文字。所以SELECT COALESCE(this_field,that_field)也可以。您可以拥有2个以上的参数...例如SELECT COALESCE(this_field,that_field,theother_field)