选择具有默认值的列或具有用户定义值的列(如果不为空)?

时间:2010-09-13 16:27:58

标签: php sql mysql schema

我正在开发一个带有一组用户可以浏览和编辑的数据的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中列表中存在的那些行?

4 个答案:

答案 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)