2014-06-08 3 views
1

내가하려는 것은 개인 기록을 추적하는 데이터베이스입니다. 모델이 거의 완료되었지만 다른 유형의 레코드를 저장하는 데 어려움을 겪고 있습니다. (I 테이블을 만들어 처음에는가변 데이터 유형의 장고 모델

... 시간, 소수점, 정수 :

의 데이터 개의 다른 종류가있다 ... 반복/바퀴, 거리, 무게, 시간이 기록되도록 또는 django의 클래스)를 사용하여 각 유형의 데이터를 찾습니다. 시간 대 테이블, 다른 가중치 (십진수) 등.

그러나 모든 레코드에 대해 하나의 테이블 만 유지하는 것이 더 나은 솔루션 일지 궁금합니다.

분리 된 테이블/모델에 대한 코드 (각 모델마다 5 가지 모델이 있습니다.) (이 방법은 잘 작동하지만 데이터를 삽입하기 위해 apropriate 모델을 미리 선택해야합니다.)

class PRWeight(model.Models): # there are PRDistance, PRLaps, PRHeight, PRTime 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    weight = decimalfield() # integer, integer, decimal, time 

    class Meta: 
     unique_together = [user, exercise, date,] 

아니면 내가 같은 것을 할 수 있고, 그 경우 좋은 또는 더 나은 솔루션이있다 : 진정한 = 나는 빈 다른 5 개 개의 필드에 대한 필드 "레코드"를 repalce 수

class PR(models.Model): 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    metric = FK(Metric) # choose between time, weight, height... 
         # the aspect beeing mesured 
    record =    # how can I call the right field type? 

또는

class PR(models.Model): 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    metric = FK(Metric) # choose between time, weight, height, distance... 
         # the aspect beeing mesured 
         # not necessary in this approach 
    wheight = decimalfield(blank=True) 
    height = decimalfield(blank=True) 
    time = timefield(blank=True) 
    distance = integerfield(blank=True) 
    laps = integerfield(blank=True) 

나는 간단한 해결책을 찾고있다. 지금까지는 직설적이기 때문에 마지막 예제를 선택하는 경향이 있지만 폼을 채울 사용자는 실수를 할 수 있습니다 ...

+0

모든 유사한 데이터를 포함하는 추상 모델을 생성 한 다음 분리합니다 모델 별 데이터를 각 데이터에 적용 할 수 있습니다. Abastract Models 또는 테이블 상속을 사용하여 응용 프로그램 논리에 따라 가장 좋은 방법을 정의 할 수 있습니다. – petkostas

+0

데이터베이스에 직접 작업하지 않는 한 테이블에 대해 걱정할 필요가 없다고 생각합니다. Django는 매우 훌륭한 ORM을 가지고 있으며 ORM의 주요 측면은 데이터베이스를 조사 할 필요가없고 저장 방법을 살펴보아야한다는 것입니다. 모든 항목과 모델에 액세스하고 ORM에서 테이블을 저장하는 데 필요한 테이블의 양을 결정할 수 있도록 클래스 계층 구조를 만들면됩니다. –

답변

1

테이블에 열 이름) true. 하나의 테이블을 사용하여 하나의 명령문을 만들 수있는 한 테이블에는 열만 있어야합니다. A (사용자, 운동, 날짜) 항상 무게와 날짜가있는 경우

넣어 많은하지만 관련 컬럼은 함께

, 하나의 테이블이있다.

그러나 (사용자, 운동, 날짜) 가중치는 가질 수 있지만 날짜는없는 경우 별도의 테이블을 사용하십시오.

-- user [user] in exercise [exercise] on [date] lifted [weight] kg 
PRlift(user,exercise,date,weight) 
-- User [user] in exercise [exercise] on [date] jumped [height] m 
PRjump(user,exercise,date,height) 

조건부 열은 복잡

세 번째 예처럼 문/테이블을 가질 수 있습니다 :

--  user [user] did [exercise] on [date] 
-- AND (lifted != blank and they lifted [weight] kg OR lifted = blank and they didn't lift) 
-- AND (jumped != blank and they jumped [height] m OR jumped = blank and they didn't jump) 
PR(user,exercise,date,weight,height) 

하지만 조합입니다 쿼리 문을 볼 수 테이블 문의 조합 인 SQL 표현식이 복잡해집니다. 기본적으로 쿼리 할 때이 테이블을 항상 조건부가 아닌 테이블 버전으로 끊어야합니다.

때때로 우리는 유형이 고정 된 부분으로 구성되어 열을 가질 수 기록 입력 열

를 사용하지 마십시오. 그러나 SQL과 같은 논리적 조건을 사용하여 파트를 쿼리하려면 대신 테이블의 열로 파트를 만들어야합니다.

-- user [user] in exercise [exercise] on [date] weighed [record.weight] kg and was [record.height] m tall 
PRrecord(user,exercise,date,record) 

SELECT * FROM PRrecord 
WHERE PRrecord.record.weight = 100 -- really, record_dot(PRrecord.record,'weight')=100 

여기서 첫 번째 점은 데이터베이스 테이블 작업이지만 두 번째 점은 프로그래밍 언어 레코드 작업입니다. DBMS는 데이터 유형 조작이 아닌 테이블 조작을 최적화하기 때문에 조회를 최적화 할 수 없습니다. 기본적으로 레코드 값을보고 나서 레코드 연산자 연산자 도트를 호출 한 다음 필드 평등을 호출 한 다음 많은 행을 버립니다. 만 점의 테이블 버전을 사용했기 때문에

SELECT * FROM PR 
WHERE PR.weight = 100 

이제 DBMS는 어떻게 점점 최적화합니다 행에 필드 평등을 결합 할 수 있습니다.

때때로 우리는 유형이 유사한 부분의 모음으로 구성되어 열을 가질 수 컨테이너 형식의 열

를 사용하지 마십시오. 그러나 SQL과 같은 논리적 조건을 사용하여 파트에 대해 쿼리하려는 경우 대신 새 테이블을 만들어야합니다. 새 테이블에는 해당 컬렉션에 대한 PK 열이 있고 이전 테이블에는 새 PK에 대한 FK 인 열이 있습니다.

-- user [user] in exercise [exercise] on [date] and their set of lifted weights in kg is [weights] 
PRlifts(user,exercise,date,weights) 

SELECT user FROM PRlifts l 
WHERE l.name = 'Fred' AND set_has_member(l.weights,200) 
AND ??? no two lifts were the same weight ??? 

나쁜. 진술이 어떻게 복잡한 지 주목하십시오. 또한 set_has_member가 테이블 조작이 아니기 때문에 DBMS는 조회를 최적화 할 수 없습니다. 심지어 어떤 조건을 쿼리 할 수도 없기 때문에 쿼리가 아닌 루프 코드를 작성해야합니다.

SELECT user FROM PRlift l 
WHERE l.user = 'Fred' AND l.weight = 200 
AND NOT EXISTS(
    SELECT weight 
    FROM Prlift l1, PRlift l2 
    WHERE l1.user = l.user AND l2.user = l.user AND l1.weight = l2.weight 
) 

이제 DBMS는 루프를 최적화하고 회피 할 수 있습니다.

(이름 길이 열을함으로써이

WHERE string_length(l1.name) = string_length(l2.name) 

인 경우 다음 DBMS 더 최적화 할 수있는 것을 알 수 있습니다. 그러나 일반적으로 DBMS 문자열 및 기타 유형의 더 많은 이하를 최적화의 특별한 지식을 가지고 마치 사실 DBMS는 레코드 유형과 집합 유형을 알 수 있지만 간단한 구문과 질의를 사용할 수는 없습니다.)