Я храню логические выражения в postgresql с таблицей, ссылающейся на себя. Пример данных выглядит следующим образом:
id operator_name operand_a_at_id operand_a_op_id operand_b_at_id operand_b_op_id
-----------------------------------------------------------------------------------
1 or 1 null 2 null
2 not 3 null null null
3 and null 1 null 2
- Каждая строка представляет операцию с не более чем двумя операндами. Оба операнда могут быть либо другой операцией, либо атомом, хранящимся в другой таблице
operator_name
должно быть ясно (арность, 1 для «не», 2 для «и» и «или» оператора * хранится в отдельной таблице) - Если левый операнд снова является операцией,
operand_a_op_id
ссылается на ту же таблицу, если левый операнд является атомом, operand_a_at_id
ссылается на таблицу атомов . - То же самое для
operand_b_op_id
и operand_b_at_id
- Если оператор унарный,
operand_b_op_id
и operand_b_at_id
равны нулю
В качестве примера Таблица выше содержит логическое выражение (1 or 2) and not 3
, где 1
, 2
и 3
- атомы. Это можно увидеть, начав со строки таблицы id==3
, которая and
связывает строки таблицы id==1
и id==2
, которые декодируются в 1 or 2
и not 3
соответственно.
Как Я мог бы получить выражение из таблицы с помощью рекурсивного sql запроса?
Я знаком с рекурсивными CTE и UNION ALL, но насколько я могу обернуть это вокруг, я могу только передавать информацию из root дерева на листьях, но для этой задачи мне понадобится обратное. Я хотел бы представить результат, как
id expression
--------------
1 "1 or 2"
2 "not 3"
3 "(1 or 2) and (not 3)"