2008-11-04 4 views
15

식의 무한 중첩을 허용하면서 데이터베이스의 부울 식을 구성하는 방법을 알고 있습니까?부울 식의 데이터 모델

예 :

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

전체 표현은 데이터 무결성을 유지하기 VARCHAR로 저장 할 수 없습니다.

+0

명확히주세요 = 넌 표현식의 결과를 저장하거나 원시 DB 열 유형에서 표현식을 재구성 할 수 있습니까? –

+0

나는 표현식을 재구성하고 싶다. –

+0

데이터베이스가 SQL/관계형이어야한다는 요구 사항이 있습니까? OODBMS를 사용할 수 있습니까? – Oddthinking

답변

8

표현은 나무 같은 구조입니다. 따라서 테이블에 트리를 표시 할 방법이 필요합니다. ,

  • 이 경우
  • 을 SecondChildID FirstChildID (... AND, OR 등)

    • ID
    • TypeExpression :

      당신은 예를 들어 필드를 사용할 수 있습니다 다음과 같은 유형이 있습니다 :

      1. AND, Children은 다른 표현식을 가리 킵니다.
      2. 또는 OR은 다른 표현식을 가리 킵니다.
      3. 같음, 자식은 다른 표현식을 가리 킵니다.
      4. Literal, FirstChild는 리터럴 테이블의 항목을 가리 킵니다.
      5. VariableLookup, FirstChild는 가변 테이블의 항목을 가리 킵니다.

      그러나 표현을 구성하는 더 좋은 방법이 있다고 생각합니다. 한때 문자열을 받아들이고 숫자 결과를 생성하는 간단한 표현식 평가기를 만들었습니다.

    13

    옵션 1은 Gamecat에서 제안한 것처럼 중첩 테이블 (id/parent_id 구조의 트리)을 사용하는 것입니다. 이것은 상대적으로 비용이 많이 들며, 하나의 중첩 된 표현식과 같은 것을 만들기 위해 SQL 쿼리를 반복적으로 발행해야합니다.

    옵션 2는 직렬화 된 개체를 사용하여 varchar 열에 저장하는 것입니다. 예를 들어 JSON을 선택하는 것이 좋습니다. 공백을 구분하지 않고 방대한 언어로 작성하고 구문 분석 할 수 있으며 데이터 무결성을 유지합니다.

    표현 문자열을 메모리의 트리 객체로 파싱하자마자 직렬화하고 저장할 수 있습니다. 데이타베이스 레벨에서 표현식을 조작 할 필요가 없다면, 나는 그 경로로 갈 것이라고 생각한다.

    +1

    여기서는 아주 좋은 지적을하고 있습니다. 단지 사용할 수 있기 때문에 옵션 1을 사용해서는 안됩니다. 옵션 1을 정당화하기위한 특정 요구 사항이 있어야합니다. 그러한 요구 사항이 임박하지 않으면 옵션 2부터 시작합니다. – Yarik

    1

    본질적으로 계층 적이며 다형성 (트리의 잎은 변수 또는 상수 일 수 있기 때문에)하기 때문에 관계형으로 표현하기가 어렵습니다.

    2

    이 유형의 표현식은 가장 일반적으로 SQL에서 쿼리하는 것을 귀찮게하는 트리 (계층 구조)로 표현됩니다.

    ab은 잠시 숫자이며 리터럴 ('1', '2')은 변수와 구별됩니다.

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

    이 구조

    은 매우 유연하지만 복잡한 표현을 검색 할 쿼리하는 (즉, "도전"읽기) "재미"가 될 것입니다.

    그리고 구문을 재구성 한 후에 시작하고 표현식을 평가해야합니다.

    2

    부울 함수를 모델링하는 전통적인 방법은 Binary Decision Diagrams, 특히 감소 된 이진 이진 의사 결정 다이어그램을 사용하는 것입니다. 개념을 잘 지원하는 DBMS 확장을 찾을 수 있습니다.

    업데이트 : 부울 논리를 쿼리 할 필요가없는 경우 BDD 라이브러리를 사용하고 BDD를 BLOB 또는 동급으로 직렬화하면됩니다. BDD 라이브러리가 데이터가 유효한지 확인할 수 있기 때문에 varchar 필드를 사용하여 상회합니다.

    내가 그것을이

    ID처럼

    TypeExpression해야한다고 생각 @Gamechat 대답에 추가

    0

    (AND, OR 등)

    FirstChildID --This이 될 수 있습니다 리프 노드 또는 동일한 테이블의 다른 행에 대한 포인터

    SecondChildID - 리프 노드 또는 동일한 테이블의 다른 행에 대한 포인터 일 수 있습니다.

    isFirstChildLeaf

    isSecondChildLeaf는

    2

    나는 VARCHAR/텍스트 열에서 폴란드어 형태로 표현을 저장하는 것입니다. 폴란드어 형식 (피연산자 이전의 피연산자, 대괄호 없음)의 표현식은 재귀 함수 (또는 스택)로 구문 분석하는 것이 훨씬 쉽습니다.

    A = 1 (b = 1 또는 b = 2) 폴란드어 형태

    는 다음과 같이 나타낸다 :

    및 1 OR = B = 1, B 2