【问题标题】:Storing boolean options in SQL在 SQL 中存储布尔选项
【发布时间】:2012-12-31 20:23:45
【问题描述】:

我正在编写代码(使用 MySQL)来解决类似于以下的问题:

有 20 个布尔选项(每个用户)。

我应该存储 20 ENUM('false','true') 还是只将这些选项的 ID 放入表中(因此每个用户可能少于 20 行)?

【问题讨论】:

  • 是否有可能出现新选项?您是否需要一次通过多个选项过滤您的用户(例如option1 = TRUE AND option2 = TRUE)?是否为每个用户设置了所有选项?百分之几的用户有选项集的非默认值?
  • 为什么不创建一个包含您的选项并拥有option_id 的表,接下来获取一个包含user_idoption_idcondition 的链接表user_options,最后拥有您的@987654329 @表和你的user_id?这样,当你添加选项时,你不需要重新设计你的 users
  • @Quassnoi:可能会出现新选项。我从不按选项过滤用户,我只在选择用户时显示所有 20 个选项的值。对于每个用户,每个选项都应该被定义(真或假),当我们添加新的选项时可能会有例外(在这种情况下,选项默认为假)。具有非默认值的用户百分比可能在 50% 左右。
  • @Tikkes:你的建议正是我考虑的两种方式之一。另一种方法是删除 condition 列并仅放置这些为 true 的 options_id。

标签: mysql sql


【解决方案1】:

如果可能会出现新选项并且您不按选项过滤,则最好使用EAV 结构(每个选项一条记录)。

这样,您可以更轻松地添加新选项(无需更改元数据)。

假设选项值是TRUEFALSE(不可能有NULL),您应该只为非默认选项值(在您的情况下为TRUE)创建记录。没有记录将意味着错误。

要检索所有选项,您可以使用:

SELECT  *, GROUP_CONCAT(CONCAT(o.id, ': ', ov.user IS NULL), ', ' ORDER BY o.id)
FROM    users u
CROSS JOIN
        options o
LEFT JOIN
        option_value ov
ON      (ov.user, ov.option) = (u.id, o.id)
GROUP BY
        u.id

,这将为您提供动态输出:

user_id   options
1         1: 0, 2: 1, 3: 0

【讨论】:

  • 什么是 EAV?添加新选项时,我应该为每个用户添加一行吗?如果我们只为真(而不是假)选项存储行,这将更容易实现。
  • @porton: en.wikipedia.org/wiki/…。如果您添加一个新选项,用户很可能会拥有此选项的默认值,该默认值在option_value 中标记为缺少值。因此,您应该只使用新选项的 id 和名称向 options 添加一条记录。
【解决方案2】:

我建议使用不同的选项创建一个 Options 表。

+---Options---+
ID
Option

+---Users---+
ID
Name

+---User_Options---+
User_id
Option_id

现在如果您需要更多选项,请将它们插入到Options 表中,您不需要以这种方式更改您的数据库。

编辑:在user_options 中删除了condition:就像提到的Quassnoi,最好只在“TRUE”的情况下添加记录,而没有记录应该被认为是“FALSE”

【讨论】:

    【解决方案3】:

    我建议将其存储为 TINYINT 0 或 1。许多框架使用 TINYINT 数据类型开箱即用,并将其作为布尔值处理。

    【讨论】:

      【解决方案4】:

      创建 3 个表。第一个是 'user_table' 。它包含用户名和 user_id。样本数据如下

      下面给出表创建脚本

      现在创建另一个名为 options_table 的表。它包含每个选项的 option_name 和 option_id。示例如下

      现在创建第三个名为“selected_options”的表。该表将用户映射到选项。它包含 user_id 和 option_id

      示例如下

      在上面的例子中 user1 选择了 option1 和 option2

      user2 选择 option1,option2 和 option3 即..option1,option2 和 option3 对于 user2 是 true

      【讨论】:

        【解决方案5】:

        我建议使用位掩码列。如果您有许多选项,而不是为每个选项创建一个新列,您将能够快速执行逐位比较。

        有关其他信息,请参阅:

        SELECT users from MySQL database by privileges bitmask?
        Implement bitmask or relational ACL in PHP
        Using bitmasks to indicate status

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-06
          • 1970-01-01
          • 2010-10-25
          • 2012-03-10
          • 1970-01-01
          • 2021-12-04
          • 1970-01-01
          • 2019-02-10
          相关资源
          最近更新 更多