【问题标题】:Data Model for Boolean Expressions布尔表达式的数据模型
【发布时间】:2010-09-20 16:13:05
【问题描述】:

您知道一种在数据库中组织布尔表达式同时允许表达式无限嵌套的方法吗?

例子:

a = 1 AND (b = 1 OR b = 2)

不应将整个表达式存储为 varchar 以保持数据完整性。

【问题讨论】:

  • 请澄清:您想存储表达式的结果还是能够从本地 DB 列类型重建表达式?
  • 我喜欢重构表达式。
  • 是否要求数据库是 SQL/关系型?你可以使用 OODBMS 吗?
  • 不,数据库必须是关系型的。

标签: database-design datamodel boolean-expression


【解决方案1】:

选项 1 是使用嵌套表(具有 id / parent_id 结构的树),就像 Gamecat 建议的那样。这样做的成本相对较高,并且需要重复发出 SQL 查询来构建等效的单个嵌套表达式。

选项 2 是使用序列化对象并将其存储到 varchar 列中。例如,JSON 将是一个不错的选择。它对空格不敏感,可以用多种语言创建和解析,并且保持数据完整性。

一旦您将表达式字符串解析为内存中的树对象,您就可以对其进行序列化并存储它。如果不需要在数据库级别操作表达式,我想我会走那条路。

【讨论】:

  • 您在这里提出了一个很好的观点:不应该仅仅因为可以使用选项1而使用它;必须有某些要求来证明选项 1 的合理性。如果这些要求不是迫在眉睫,我可能会从选项 2 开始。
【解决方案2】:

表达式是一个树状结构。所以你需要一种在表格中呈现树的方法。

例如,您可以使用以下字段:

  • 身份证
  • TypeExpression (and, or etc...)
  • FirstChildID
  • SecondChildID

在这种情况下,您有以下类型:

  1. AND,子项指向其他表达式。
  2. OR,子项指向其他表达式。
  3. 相等,子项指向其他表达式。
  4. 文字,FirstChild 指向文字表中的条目。
  5. VariableLookup,FirstChild 指向变量表中的条目。

但我认为有更好的方式来组织表达。我曾经做过一个简单的表达式求值器,它接受一个字符串并产生一个数字结果。

【讨论】:

    【解决方案3】:

    这种类型的表达式通常表示为树(层次结构),众所周知,在 SQL 中查询很烦人。

    我们暂时假设 ab 是数字,并且文字('1','2')与变量区分开来。

    Table Nodes
    id
    type (Variable|Literal)
    name (nullable for literal)
    value
    
    Table Operators
    id
    name (=, AND, OR, NOT)
    leftNodeId
    rightNodeId
    

    这种结构非常灵活,但查询它以检索复杂的表达式会很“有趣”(读作“具有挑战性”)。

    你仍然需要解析结构,并在重建后评估表达式。

    【讨论】:

      【解决方案4】:

      我会将表达式以波兰语形式存储在 varchar/text 列中。波兰语形式的表达式(操作数在操作数之前,没有括号)更容易使用递归函数(或当然是堆栈)进行解析。

      a = 1 AND (b = 1 OR b = 2)

      波兰语形式如下:

      AND = a 1 OR = b 1 = b 2

      【讨论】:

        【解决方案5】:

        这将很难以关系表示,因为它的本质是分层和多态的(树的叶子可以是变量或常量)。

        【讨论】:

          【解决方案6】:

          对布尔函数建模的传统方法是使用Binary Decision Diagrams,尤其是降阶二元决策图。您可能会找到为您的 DBMS 提供良好支持的扩展。

          更新: 或者,如果您不需要查询布尔逻辑,您可以使用 BDD 库并将 BDD 序列化为 BLOB 或等效项。它优于使用 varchar 字段,因为 BDD 库将确保数据有效。

          【讨论】:

            【解决方案7】:

            答案没问题,但如果表达式组中有超过 2 个表达式怎么办?

            a = 1 AND (b = 1 OR b = 2 OR b = 3)
            

            我建议这样做:

            -------------------
            |    Condition    |
            -------------------
            | - id            |
            | - value1        |
            | - value2        |
            | - operation     |
            -------------------
                |(1)
                |        --------------
                |       |              |
                |       |(*)           |
            -------------------        |
            | ConditionGroup  |        |
            -------------------        |
            | - id            |--------
            | - groupType     |
            | - condition     |
            | - subConditionGroups
            -------------------
            
            • value1value2operation 模拟最终比较,如“b = 3”(在我的情况下为 value1 = 'b'value2 = '3'operation = 'EQUALS'
            • groupeType 可以是“AND”或“OR
            • ConditionGroup 可以有ConditionGroups 的子列表最终的Condition,但不能同时拥有
            • 现在您的起始表达式是ConditionGroup,递归地挖掘它的subConditionGroups,直到找到最终条件,然后返回值并应用正确的condition

            其实这就是我要尝试的。

            【讨论】:

              【解决方案8】:

              添加到@Gamechat 答案

              我觉得应该是这样的

              身份证

              TypeExpression (and, or etc...)

              FirstChildID -- 这可以是叶节点或指向同一表中另一行的指针

              SecondChildID --这可以是叶节点或指向同一表中另一行的指针

              isFirstChildLeaf

              isSecondChildLeaf

              【讨论】:

                猜你喜欢
                • 2011-05-25
                • 1970-01-01
                • 2016-01-21
                • 2010-09-21
                • 2012-04-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多