2010-04-15 2 views
1

나는 하나의 테이블 사람이 있습니다세로 테이블을 가로 테이블로 변환하는 방법은 무엇입니까?

Id Name 
1 Person1 
2 Person2 
3 Person3 

을 그리고 나는 그것의 자식 테이블 프로필이 있습니다

Id PersonId FieldName Value 
1 1  Firstname Alex 
2 1  Lastname Balmer 
3 1  Email  [email protected] 
4 1  Phone  +1 2 30004000 

을 그리고는 다음과 같이 하나 개의 행이 두 테이블에서 데이터를 얻으려면 :

Id Name  Firstname Lastname Email    Phone 
1 Person1 Alex  Balmer [email protected] +1 2 30004000 
  1. 이러한 세로 (키, 값) 값을 한 행에 입력하는 데 가장 최적화 된 쿼리는 무엇입니까? 이제 네 개의 필드를 가져와야하기 때문에 부모 테이블에 자식 테이블의 네 조인을 했으므로 문제가 발생했습니다. 일부 최적화가 가능합니다.
  2. 새 필드 (키, 값)를 추가 할 때이 쿼리를 쉽게 수정할 수 있습니다. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 일부 저장 프로 시저를 만들려면 어떻게해야합니까?

내 DB 계층 (C#)에 강하게 입력하고 LINQ (프로그래밍 할 때)를 사용하고 싶습니다. 그래서 새로운 키를 추가 할 때 프로필 테이블의 값 쌍을 최소한으로 수정하고 싶습니다. 가능한 경우 DB 및 C#. 사실이 경우에는 몇 가지 모범 사례를 얻으려고합니다.

+1

쿼리가 어떤 열을 내야하는지 디자인 타임에 알면 왜 프로필 테이블에 개방형 필드 구조가 필요합니까? –

답변

1
Select 
    P.ID 
    , P.Name 
    , Case When C.FieldName = 'FirstName' Then C.Value Else NULL END AS FirstName 
    , Case When C.FieldName = 'LastName' Then C.Value Else NULL END AS LastName 
    , Case When C.FieldName = 'Email' Then C.Value Else NULL END AS Email 
    , Case When C.FieldName = 'Phone' Then C.Value Else NULL END AS Phone 
From Person AS P 
Inner JOIN Child AS C 
ON P.ID = C.PersonID 

PIVOT을 사용할 수 있습니다. 새 열을 추가하는 것이 가장 쉬운 것이 확실하지 않습니다.

CREATE TABLE Persons 
(PersonID  int identity(1,1) primary key 
,Firstname varchar(...) 
,Lastname  varchar(...) 
,Email  varchar(...) 
,Phone  varchar(...) 
,.... 
) 

다음 가장 최적화 된 쿼리는 다음과 같습니다 :

SELECT 
    PersonID,Firstname,Lastname,Email,Phone 
    FROM Persons 
    WHERE ... 

이 사람 테이블에 모든 주요 열을 추가 강력한 형식의 필드

1

가장 최적화 된 방법은 이런 식으로하는 것입니다. 당신이 전문해야하는 경우 추가 테이블을 만들 : 무제한 동적 속성 필드를 가지고있는 경우

--one person can play many instruments with this table 
CREATE TABLE PersonMusicians 
(PersonID    int   --pk fk to Persons.PersonID  
,InstrumentCode   char(1)  --pk 
,... 
) 

--only one row per person with this table 
CREATE TABLE PersonTeachers 
(PersonID    int   --pk fk to Persons.PersonID  
,FavoriteSubjectCode char(1) 
,SchoolName    varchar(...) 
) 

, 그럼 내가 (가능한 한 많은 일반 필드로)로 완전히 가능한 한 위의 구조를 만드는 것입니다 다음이에 " 이 같은 모든 정보를 저장 AdditionalInfo "테이블 :

AdditionalInfoFields 
FieldID int identity(1,1) primary key 
FieldName varchar(...) 

AdditionalInfo 
AdditionalInfoID int identity(1,1) primary key 
PersonID   int fk to Persons.PersonID 
FieldID   int fk to AdditionalInfoFields.FieldID  
FieldValue   varchar(..) or you can look into sql_variant 

AdditionalInfo.PersonID+FieldID에 인덱스가 있고이 중 어느 AdditionalInfo.FieldID+PersonID

짧은처럼 또한 다음 X 속성이있는 모든 사람, 다른 검색한다면 쿼리에 가입

SELECT 
    P.ID, p.Name 
     , p1.Value AS Firstname 
     , p2.value AS Lastname  
     , p3.Value AS Email 
     , p4.Value AS Phone 
    FROM Persons     p 
     LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Firstname' 
     LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Lastname' 
     LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Email' 
     LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Phone' 
    WHERE .... 

당신은 항상이 4 중 인덱스와 구체화 된 뷰를 만들 수있는 왼쪽과이 : 위, 당신은 당신이 당신의 옵션 # 1에서 언급 한 것처럼 네 왼쪽 외부 조인을 사용해야합니다 속도를 높여야하는 데이터가 미리 계산됩니다.

관련 문제