2010-04-15 7 views
1

У меня есть одна таблица Person:Как преобразовать вертикальную таблицу в горизонтальную таблицу?

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. Я хочу, чтобы иметь возможность изменить этот запрос простым способом, когда я добавляю новое поле (ключ, значение). Каков наилучший способ сделать это? Чтобы создать хранимую процедуру?

Я хотел бы иметь сильно типы в моем уровне БД (C#) и использовать LINQ (при программировании), поэтому это означает, что когда я добавляю новую пару Key, Value в таблицу Profile, я хотел бы сделать минимальные изменения в 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; не уверен, какой из них будет проще всего добавить новый столбец.

1

лучший оптимизированный способ с сильно типизированных полей, чтобы сделать это таким образом:

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 ... 

Добавить все основные столбцы в таблице лиц. если вам нужно специализироваться создать дополнительные таблицы:

--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, и если вы будете искать для всех людей, которые имеют X атрибут, то и другой, как AdditionalInfo.FieldID+PersonID

не хватает какой-либо из выше, вам нужно будет использовать четыре левых внешнее соединение, как вы упомянули в своем опции # 1:

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 .... 

вы всегда можете сделать материализованное представление с индексом из этого-слева присоединиться запросом и иметь данные, предварительно рассчитанные для вас, которые должны ускорить его.

Смежные вопросы