2008-10-01 3 views
6

컴퓨터와 해당 사용자를 나타내는 데 필요한 데이터베이스를 작업하고 있습니다. 각 컴퓨터는 여러 사용자를 가질 수 있으며 각 사용자는 여러 컴퓨터와 연결할 수 있으므로 고전적인 다 대다 관계입니다. 그러나 "기본"사용자의 개념이 필요합니다. 기본 사용자와 함께 모든 컴퓨터를 기본 사용자와 함께 나열 할 수 있어야합니다. 데이터베이스에서 가장 좋은 방법이 무엇인지 잘 모르겠습니다."기본"이 포함 된 다 대다

1) 현재 수행중인 작업 : 테이블을 부울 IsPrimary 열과 연결 중입니다. 가입하려면 ON (c.computer_id = l.computer_id AND l.is_primary = 1)과 같은 것이 필요합니다. 작동하지만 데이터가 컴퓨터 당 한 명의 기본 사용자 만 갖도록 제한하는 것이 쉽지 않기 때문에 잘못 생각합니다.

2) 사용자 테이블의 모든 행은 컴퓨터 테이블의 사용자 행을 직접 가리키는 필드로, 주 사용자가 아닌 사용자를 나타냅니다. 이것은 컴퓨터 당 1 차 제약을 더 잘 나타내지 만 컴퓨터 사용자의 목록을 더 세게 얻습니다.

3) 연결 테이블의 행에 연결되는 컴퓨터 테이블의 필드. 이상하게 느껴진다 ...

4) 다른 것?

이 관계를 설명하는 '관계형'방법은 무엇입니까?

편집 : @ Mark Brackett : 세 번째 옵션은 얼마나 멋진 지 보여 주었기 때문에 나에게 이상하지 않습니다. 나는 어떤 이유로 복합 외래 키를 사용하지 않는다고 생각했기 때문에 링크 테이블에 ID 컬럼을 추가하여 작동하도록해야한다고 생각했습니다. 좋은데, 고마워!

@ j04t : 차갑고, 지금 # 3에 다행입니다.

+0

의 단순함을 표시하려면? – albertein

+0

연결 테이블에 주어진 컴퓨터의 모든 사용자가 포함되어 있지 않기 때문에. –

답변

7

옵션 3, 이상하게 느껴질 수 있지만, 모델링하려는 것과 가장 가까운 것입니다. 당신은 같은 것을 할 거라고 : 당신은 0 또는 1 주 사용자 (당신이 원하는 경우 PrimaryUserId이 널 (NULL) 일 수있다)를 제공

User { 
    UserId 
    PRIMARY KEY (UserId) 
} 

Computer { 
    ComputerId, PrimaryUserId 
    PRIMARY KEY (UserId) 
    FOREIGN KEY (ComputerId, PrimaryUserId) 
     REFERENCES Computer_User (ComputerId, UserId) 
} 

Computer_User { 
    ComputerId, UserId 
    PRIMARY KEY (ComputerId, UserId) 
    FOREIGN KEY (ComputerId) 
     REFERENCES Computer (ComputerId) 
    FOREIGN KEY (UserId) 
     REFERENCES User (UserId) 
} 

을, 그 Computer_User에 있어야합니다. 편집 : 사용자가 1 대의 컴퓨터에 대해서만 기본 서버가 될 수 있으면 Computer.PrimaryUserId의 고유 컨 스트레인 트가이를 시행합니다.모든 사용자가 일부 컴퓨터의 주 사용자 (즉, 1 : 1 관계 일 때 동일한 사용자가 동일한 테이블에 있어야한다는 요구 사항이 없음)에 유의하십시오.

편집 : 일부 쿼리는 당신에게이 점 2의 컴퓨터 사용자를 나열하기 어려운 이유는이 디자인

--All users of a computer 
SELECT User.* 
FROM User 
JOIN Computer_User ON 
    User.UserId = Computer_User.UserId 
WHERE 
    Computer_User.ComputerId = @computerId 

--Primary user of a computer 
SELECT User.* 
FROM User 
JOIN Computer ON 
    User.UserId = Computer.PrimaryUserId 
WHERE 
    Computer.ComputerId = @computerId 

--All computers a user has access to 
SELECT Computer.* 
FROM Computer 
JOIN Computer_User ON 
    Computer.ComputerId = Computer_User.ComputerId 
WHERE 
    Computer_User.UserId = @userId 

--Primary computer for a user 
SELECT Computer.* 
FROM Computer 
WHERE 
    PrimaryUserId = @userId 
+0

FK 컴퓨터 -> CompUser는 컴퓨터의 기본 사용자가 실제로 해당 컴퓨터 사용자 중 하나임을 강요합니다. 엄격 함이 좋다 :) – helios

+0

게시물을 보내 주셔서 감사합니다. 그것은 처음에는 외국어로 보이는 방식으로 관계를 바라 보았지만, 실제로 잘 작동합니다. –

+0

나는 그것을 좋아했다! 이론적 인 관점에서 우리는 "일대 다"관계가 "컴퓨터의 주 사용자"라고 말하면서 "다자간"관계 인 "is 컴퓨터의 사용자 "입니다. 누군가이 제안에 대한 제한 사항을 보았습니까? –

0

기본 사용자는 컴퓨터와 사용자의 기능이므로 primaryUser가 연결 테이블의 열이되는 방식을 사용하는 경향이 있습니다.

내가 생각할 수있는 또 다른 대안은 primaryUser 열을 컴퓨터 테이블 자체에 직접 저장하는 것입니다.

0

computer_id에 고유 한 PRIMARY_USERS 테이블을 만들고 computer_iduser_id USERS의 외래 키를 모두 만들 수 있습니다.

0

해결 방법 1 또는 2가 작동합니다. 이 시점에서 어느 것이 더 쉽게 작업 할 수 있는지 스스로에게 묻습니다. 필자는 일반적으로 연결 테이블에 깃발을 놓은 다음 computer_id 및 isPrimaryUser에 고유 한 제약 조건을 적용하여 각 컴퓨터에 기본 사용자가 하나만 있는지 확인하기 위해 두 가지 방법을 서로 다른 상황에서 사용했습니다.

+0

중복 된 computer_id, isPrimaryUser 값이있는 기본 사용자가 아닌 명백한 결함을 제외하고는 ... –

+0

user_id와 isPrimaryUser도 고유해야하므로 두 번째 고유 키를 구현하십시오. 가정의 모든 것을 하나의 테이블에 보관합니다. –

+0

IsPrimaryUser는 0 또는 1 일 수 있습니다. 따라서 (UserId, IsPrimary) 고유 키는 사용자가 * 많고 * 기본 사용자가 1 명 (UserId, IsPrimary = 0) 및 기본 사용자가 1 명 (UserId, IsPrimary = 1) . Your (ComputerId, IsPrimary)도 비슷한 결함이 있습니다. –

0

2는 나에게 맞는 것처럼 느껴지지만 일반적으로 수행하는 일종의 쿼리 및 사용자가 보유한 데이터 볼륨의 종류에 대해 성능을 테스트하기 위해 1, 2 및 3을 테스트 할 것입니다.

일반적인 선택 규칙이있는 곳에서는 쿼리 요구 사항을 조사하고 스키마를 디자인하여 가장 일반적인 경우에 최상의 성능과 리소스 활용률을 얻을 수 있어야한다고 생각하는 경향이 있습니다.

드문 경우이지만 똑같이 일반적인 경우에는 반대 구현을 제안하지만 Occam의 면도기를 사용하십시오.

+0

관계형 모델링에 관해서는 많은 선택의 여지가 없다고 생각합니다. 올바른 방법과 잘못된 방법이 있습니다. 잘못된 길은 더 잘 수행 될 수 있지만 유지 관리 문제 일 수 있습니다. 때로는 그 거래를해야하지만 의식적으로 선택해야합니다. –

+0

후속 작업 - 사용자가 Computer.PrimaryUserId에있는 기본 사용자와 Computer_User에있는 기본 사용자가 아닌 동일한 컴퓨터에서 동일한 사용자가 될 수 있으므로 옵션 2는 * wrong *입니다. 시각. –

1

편집 - 처음 세 번에 대해 제대로 생각하지 않았습니다 ... 내가 투표 - (번호 3 용액)

사용자

user id (pk) 

컴퓨터

computer id (pk) 
primary user id (fk -> computer users id) 

컴퓨터 사용자

user id (pk) (fk -> user id) 
computer id (pk) (fk -> user id) 

이 내가 생각할 수있는 가장 좋은 방법입니다 .

왜이 디자인이 마음에 드는지.

1) 이것은 컴퓨터와 사용자와 관련된 관계이므로 기본 사용자로 여러 컴퓨터에 사용자를 연결할 수 있다는 생각을 좋아합니다. 그러나이 데이터베이스가 사용되는 곳에서는 발생하지 않을 수도 있습니다.

2) 링크 테이블

(computer_users.primary_user_id fk-> users.user_id) 

에 primary_user을 가진 싫어하는 이유는 지금까지 여러 주 사용자를 가진에서 컴퓨터를 방지하는 것입니다.

다른 접근법에서 볼 수있는 몇 가지 가능한 문제에 결코 빠지지 않기 때문에 3 번 해결책이 더 좋아 보인다.

해결 방법 1 문제 - 컴퓨터 당 여러 명의 기본 사용자가있을 수 있습니다.

문제 2 - 컴퓨터와 사용자가 서로 연결되어 있지 않을 때 컴퓨터가 기본 사용자에게 연결됩니다.

computer.primaryUser = user.user_id 
computer_users.user_id != user.user_id 

해결 방법 3 문제 - 이상하게 보입니까? 그 외에는 아무것도 생각할 수 없다.

해결 방법 4 문제 - 다른 방법으로 생각할 수 없습니다.


이것은 네 번째 편집이므로 아직 이해할 수 있기를 바랍니다.

+0

"기본"사용자를 결정하는 문제는 여전히 해결되지 않습니다. – Mark

0

우리는 응용 프로그램에서 비슷한 상황에 처해 있는데 많은 고객이 연결될 수있는 계정을 가지고 있지만 단 하나만 주 고객이되어야합니다.

링크 테이블을 사용하지만 링크 테이블에 시퀀스 값이 있습니다. Primary user는 Sequence = 1을 가진 사용자입니다. AccountID와 Sequence에 대한 해당 Link 테이블에 Index가 있습니다. AccountID과 Sequence의 조합이 고유하도록합니다 (따라서 두 고객이 주 고객이 될 수 없음을 보증합니다). 계정). 따라서 당신은 다음과 같이 나타낼 수 있습니다 :

LEFT JOIN c.computer_id = l.computer_id AND l.sequence = 1