【问题标题】:Using Null field to represent something?使用 Null 字段来表示什么?
【发布时间】:2012-10-06 19:55:44
【问题描述】:

可以在deal.tariff_id中使用'NULL'值来表示它属于tariff_data表中affiliate_id=3中的任何关税吗?

例如:

mysql> select * from phone;
+----+------------------+
| id | name             |
+----+------------------+
|  4 | HTC Sensation XL |
| 26 | iPhone 4s        |
| 25 | iPhone 5         |
| 24 | Nokia C3-01      |
+----+------------------+

mysql> select * from tariff;
+----+-----------------+-----------------+--------------+-------------+
| id | name            | tariff_duration | monthly_cost | description |
+----+-----------------+-----------------+--------------+-------------+
|  1 | Business Plan 1 |              24 |         5.00 |             |
|  2 | Business Plan 2 |              24 |        10.00 |             |
|  4 | Business Plan 3 |              24 |        15.52 |             |
|  5 | Business Plan 4 |              24 |        18.52 |             |
|  8 | Super Plan      |              12 |        15.00 |             |
+----+-----------------+-----------------+--------------+-------------+

mysql> select * from tariff_data;
+----+-----------+--------------+-------+
| id | tariff_id | affiliate_id | bonus |
+----+-----------+--------------+-------+
|  1 |         1 |            3 | 34.00 |
|  2 |         2 |            3 | 44.00 |
|  5 |         3 |            3 | 10.00 |
|  6 |         4 |            3 | 10.00 |
|  7 |         5 |            3 | 10.00 |
+----+-----------+--------------+-------+

deal 表中,您可以看到affiliate_id=3tariff_id=NULL 属于tariff_data 表中列出的任何关税。我这样做是为了减少deal 中的行数。如果我不包含 NULL,则意味着我必须包含许多 tariff_id 和相同的 phone_id,反之亦然。

mysql> select * from deal;
+----+----------+-----------+--------------+--------+
| id | phone_id | tariff_id | affiliate_id | active |
+----+----------+-----------+--------------+--------+
|  1 |        4 |      NULL |            3 |      1 |
|  3 |       24 |      NULL |            3 |      1 |
|  9 |       24 |         8 |            4 |      1 |
| 10 |       25 |         8 |            4 |      1 |
| 11 |       26 |         8 |            4 |      1 |
+----+----------+-----------+--------------+--------+

更新,例如我没有使用NULL值:

mysql> select * from deal;
+----+----------+-----------+--------------+--------+
| id | phone_id | tariff_id | affiliate_id | active |
+----+----------+-----------+--------------+--------+
|  1 |        4 |         1 |            3 |      1 |
|  2 |        4 |         2 |            3 |      1 |
|  3 |       24 |         1 |            3 |      1 |
|  4 |       24 |         2 |            3 |      1 |
|  5 |       24 |         3 |            3 |      1 |
|  6 |       24 |         4 |            3 |      1 |
|  7 |       24 |         5 |            3 |      1 |
|  9 |       24 |         8 |            4 |      1 |
| 10 |       25 |         8 |            4 |      1 |
| 11 |       26 |         8 |            4 |      1 |
+----+----------+-----------+--------------+--------+

【问题讨论】:

    标签: mysql database database-design relational-database


    【解决方案1】:

    有很多方法可以达到预期的结果,但使用比 NULL 更合乎逻辑的方法。

    正如 Oded 所指出的,NULL 表示缺少的未知值

    • 可能有一个列来指示所有权
    • 标准化
    • 使用现有列“tariff_id”作为具有非空值的所有权指标

    【讨论】:

    • 请显示您所指的“表示所有权的列”示例以及您将如何规范化
    • 您似乎使用 tarrif_id 列作为此指标,否?非 NULL 值当前代表什么?至于规范化,我并不是强烈建议这样做——我只是列出了常见的解决方案。您的表格看起来已经正常化了。
    • 如果我使用tarrif_id 列作为NULL 这意味着它表明phone_id 属于任何tariff_data 表(deal.affiliate_id = tariff_data.affiliate_id)。 None NULL 值目前表示获取deal.tariff_id = tariff.id之间的相关记录
    • 很公平 - 这可能会成为哲学问题,但我会(个人)做的是使用 NON NULL int 值来表示“任何”所有权。 MySQL 将NULL 定义为“缺失的未知值”。这种使用实际上是“任何”所有权的“已知价值”。同样,您可以想象使用 null 来表示“任何”,这似乎是有限的并且可能令人困惑。
    • 我明白你的意思。我可以为deal 表中的每个phone_id 定义所有tariff_id,但是如果您知道我的意思,它会变得非常大吗?我已经更新了我的问题,所以你可以看到我的意思。
    【解决方案2】:

    与其他两个答案一样,这不是一个好主意。这是规范化的建议。

    您希望某些交易代表“一般”交易,而不考虑关税。您可以将 deail 表拆分为两个,一个用于简单交易,一个用于一般交易:

    mysql> select * from deal_simple;
    +----+----------+-----------+--------------+--------+
    | id | phone_id | tariff_id | affiliate_id | active |
    +----+----------+-----------+--------------+--------+
    |    |       24 |         8 |            4 |      1 |
    |    |       25 |         8 |            4 |      1 |
    |    |       26 |         8 |            4 |      1 |
    +----+----------+-----------+--------------+--------+
    
    mysql> select * from deal_general_tariff;
    +----+----------+--------------+--------+
    | id | phone_id | affiliate_id | active |
    +----+----------+--------------+--------+
    |    |        4 |            3 |      1 |
    |    |       24 |            3 |      1 |
    +----+----------+--------------+--------+
    

    然后您可以通过简单查询获得扩展结果(我假设您没有错误地包含与 phone_id 4tariff_id 3, 4, 5 相关的另外 3 行):

    SELECT phone_id, tariff_id, affiliate_id, active
    FROM deal_simple
    
    UNION
    
    SELECT dgt.phone_id, td.tariff_id, dgt.affiliate_id, dgt.active
    FROM 
        deal_general_tariff AS dgt
      JOIN 
        tariff_data AS td
          ON td.affiliate_id = dgt.affiliate_id ;
    

    【讨论】:

    • 这是一个绝妙的主意,非常感谢!只是一个快速的问题。将有一些关税是“Sim Only Deal”(在tariff 表中),这意味着它不随手机提供。你会把它放在deal_simpledeal_general_tariffphone_id = NULL 中吗?
    • 您的意思是独立于手机的交易?然后你可以有一个deal_general_phone,它的所有列都为deal,除了phone_id(与上述相同)
    • 没有。例如,客户想要订购 Sim-Only 合同(资费),但他们已经拥有一部手机。他们想要订购 Sim-Only 合同(资费)而没有电话。从这个意义上说。可能像 deal_without_phonedeal_simonly
    【解决方案3】:

    不是个好主意。

    NULL 表示未知值。事实并非如此,用它来有特定的含义会反过来咬你。

    首先,任何接触系统部分(代码和 SQL)的人都必须知道并记住该约定。

    其次,它是不可扩展的——如果你需要一些东西来代表所有带有affiliate_id of 4 的 tarrifs 怎么办?

    第三——如果你真的需要使用NULL,你会怎么做?

    【讨论】:

      【解决方案4】:

      不是个好主意。基本问题是 NULL 已经意味着三个不同的东西,这使它们成为问题。你在问问题。它代表的是:

      1. 未知值(即未输入,预计存在)。这意味着 NULL || 'mytext' 为 NULL。
      2. 值已知不存在(例如,在街道地址的第二行使用 NULL)。这是有问题的,但很难避免。在非 Oracle 平台上,空字符串在这里更适合字符类型。看起来你正在称这个体重。
      3. 在外部联接的结果中找不到值

      这意味着在处理 NULL 值时,您已经准备好三种不同的情况,并且必须使用上下文来解决。如果您可以将含义减少到两个,或者更好的是 1(外部连接未找到记录),那么您的情况会更好,并且您需要担心的情​​况更少。

      当一个人期望有两个值之一时,问题当然必须做,例如employee.hourly_wage 或employee.monthy_salary。这当然是一个不好的例子,因为可以做工资或工资加上工资单位,但问题很普遍。很多时候,您必须在完美规范化和避免列中的空值和丰富的跨列数据约束之间进行权衡。

      【讨论】:

        【解决方案5】:

        不要使用 NULL 来传达消息。使用 NULL 表示没有值。

        值的缺失可能意味着值存在但未知。此案由 Oded 报道。

        这也可能意味着某个值在这种情况下不适用。当表包含描述给定类的对象的行时,通常会发生这种情况,但有多个子类扩展了该类。某些列可能与某些子类有关,但与其他子类无关。

        如果需要,您可以通过一种在 SO 中具有名为“类表继承”的标记的技术来解决最后一种情况。

        如果数据的读者从缺少值中得出推论,他们可以。但推理不是交流。

        【讨论】:

          猜你喜欢
          • 2011-01-11
          • 2012-08-11
          • 1970-01-01
          • 2011-04-24
          • 2021-06-15
          • 2016-10-27
          • 2017-01-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多