您知道一种在数据库中组织布尔表达式同时允许表达式无限嵌套的方法吗?
例子:
a = 1 AND (b = 1 OR b = 2)
整个表达式不应存储为 varchar 以保持数据完整性。
您知道一种在数据库中组织布尔表达式同时允许表达式无限嵌套的方法吗?
例子:
a = 1 AND (b = 1 OR b = 2)
整个表达式不应存储为 varchar 以保持数据完整性。
选项 1 是使用嵌套表(具有 id / parent_id 结构的树),就像 Gamecat 建议的那样。这样做的成本相对较高,并且需要重复发出 SQL 查询来构建等效的单个嵌套表达式。
选项 2 是使用序列化对象并将其存储到 varchar 列中。例如,JSON 将是一个不错的选择。它对空格不敏感,可以用大量语言创建和解析,并且保持数据完整性。
一旦您将表达式字符串解析为内存中的树对象,您就可以对其进行序列化并存储它。如果不需要在数据库级别操作表达式,我想我会走那条路。
表达式是树状结构。因此,您需要一种在表格中呈现树的方法。
例如,您可以使用以下字段:
在这种情况下,您有以下类型:
但我认为有更好的方式来组织表达。我曾经做过一个简单的表达式求值器,它接受一个字符串并产生一个数字结果。
这种类型的表达式最通常表示为树(层次结构),众所周知,在 SQL 中查询很烦人。
我们将假设a
和b
目前是数字,并且文字('1','2')与变量区分开来。
Table Nodes
id
type (Variable|Literal)
name (nullable for literal)
value
Table Operators
id
name (=, AND, OR, NOT)
leftNodeId
rightNodeId
这种结构非常灵活,但查询它以检索复杂的表达式将是“有趣的”(读作“具有挑战性的”)。
并且您仍然必须解析结构以开始并在重建后评估表达式。
我会将表达式以波兰语形式存储在 varchar/text 列中。波兰语形式的表达式(操作数在操作数之前,没有括号)更容易用递归函数(当然也可以是堆栈)解析。
a = 1 与(b = 1 或 b = 2)
以波兰语形式显示如下:
与 = a 1 或 = b 1 = b 2
对布尔函数建模的传统方法是使用二元决策图,尤其是降阶二元决策图。您可能会找到为您的 DBMS 提供良好支持的扩展。
更新:或者,如果您不需要查询布尔逻辑,您可以使用 BDD 库并将 BDD 序列化为BLOB
或等效。它优于使用varchar
字段,因为 BDD 库将确保数据有效。
这将很难以关系方式表示,因为就其性质而言,它既是分层的又是多态的(树的叶子可以是变量或常量)。
好的答案,但如果表达式组中有超过 2 个表达式怎么办?
a = 1 AND (b = 1 OR b = 2 OR b = 3)
我建议:
-------------------
| Condition |
-------------------
| - id |
| - value1 |
| - value2 |
| - operation |
-------------------
|(1)
| --------------
| | |
| |(*) |
------------------- |
| ConditionGroup | |
------------------- |
| - id |--------
| - groupType |
| - condition |
| - subConditionGroups
-------------------
value1
,value2
并operation
为最终比较建模,例如 ' b = 3
' (在我的情况下value1 = 'b'
,value2 = '3'
和operation = 'EQUALS'
)groupeType
可以是' AND
'或' OR
'ConditionGroup
的子列表或final但不能同时有。ConditionGroup
Condition
ConditionGroup
,递归地挖掘它subConditionGroups
直到找到最终条件,然后返回值并应用正确的condition
。其实这就是我要尝试的。
Adding to @Gamechat answer
I think it should be like this
ID
TypeExpression (and, or etc...)
FirstChildID --This can be a leaf node or a pointer to another row in same table
SecondChildID --This can be a leaf node or a pointer to another row in same table
isFirstChildLeaf
isSecondChildLeaf