2013-07-09 2 views
1

Моя текущая схема выглядит следующим образом:Сведение 1-ко-многим

PersonType (PersonTypeID, Name, Description) 

Person (PersonID,PersonTypeID, FirstName, ...) 

PersonDynamicField (PersonDynamicFieldID, PersonTypeID, Name, Description, DataType, DefaultValue, ...) 

PersonDynamicFieldValue (PersonDynamicFieldValueID, PersonDynamicFieldID, PersonID, Value, ...) 

То есть, человек определенного типа. Например, Клиент. Для каждого PersonType можно динамически добавлять дополнительные поля для хранения около PersonType. Для Клиента нам может понадобиться добавить поля в PersonDynamicField, такие как LikesChocolate, FavoriteColor, HappinessScale и т. Д. Затем значение для этих полей будет сохранено в PersonDynamicFieldValue.

Надеюсь, что мое письмо имеет смысл.

То, что я хотел бы сделать, это запрос, который может сгладить эту структуру и возвращает результат, глядя, как это:

PersonID, PersonTypeID, FirstName, LikesChocolate, FavoriteColor, HappinessScale 
1, 2, Robert, 1, Green, 9 
2, 2, John, 0, Orange, 5 
... 

Я вроде застрял и не знаю, где даже начать ,

Вы можете помочь?

ответ

4

Для получения результата, который вы хотите, вы можете преобразовать строки данных в столбцы несколькими способами.

Начиная с SQL Server 2005 вы можете использовать функцию PIVOT. Базовая структура кода будет:

SELECT personid, persontypeid, firstname,[FavoriteColor],[HappinessScale],[LikesChocolate] 
from 
( 
    select p.personid, p.persontypeid, p.firstname, f.name fields, v.value 
    from person p 
    inner join persontype pt 
    on p.persontypeid = pt.persontypeid 
    left join PersonDynamicField f 
    on p.PersonTypeID = f.PersonTypeID 
    left join PersonDynamicFieldValue v 
    on f.PersonDynamicFieldID = v.PersonDynamicFieldID 
    and p.personid = v.personid 
) x 
pivot 
( 
    max(value) 
    for fields in ([FavoriteColor],[HappinessScale],[LikesChocolate]) 
) p; 

См SQL Fiddle with Demo. Единственная проблема, с которой вы столкнетесь с PIVOT, заключается в том, что она требует, чтобы значения, которые были преобразованы в столбцы, известны во время выполнения. Для вашей ситуации это кажется невозможным, поскольку значения могут меняться. В результате, вам придется использовать динамический SQL, чтобы получить результат:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Name) 
        from PersonDynamicField 
        where PersonTypeID = 2 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT personid, persontypeid, firstname,' + @cols + ' 
      from 
      (
       select p.personid, 
       p.persontypeid, 
       p.firstname, 
       f.name fields, 
       v.value 
       from person p 
       inner join persontype pt 
       on p.persontypeid = pt.persontypeid 
       left join PersonDynamicField f 
       on p.PersonTypeID = f.PersonTypeID 
       left join PersonDynamicFieldValue v 
       on f.PersonDynamicFieldID = v.PersonDynamicFieldID 
       and p.personid = v.personid 
      ) x 
      pivot 
      (
       max(value) 
       for fields in (' + @cols + ') 
      ) p ' 


execute(@query); 

См SQL Fiddle with Demo. Они приведут к следующему:

| PERSONID | PERSONTYPEID | FIRSTNAME | FAVORITECOLOR | HAPPINESSSCALE | LIKESCHOCOLATE | 
----------------------------------------------------------------------------------------- 
|  1 |   2 | Robert |   Green |    9 |    1 | 
|  2 |   2 |  John |  Orange |    5 |    0 | 
+0

Большое спасибо @bluefeet. Это то, что я искал, и делает то, что мне нужно. Только одно: не могли бы вы кратко объяснить заявление, начинающееся с «Select @cols ...»? Я знаю, что он делает, но не совсем понимаю, как это сделать. Спасибо. – PostureOfLearning

+0

@Rob Это генерирует список различных имен полей для каждого идентификатора типа лица. При использовании PIVOT столбцы должны быть известны во время выполнения, поэтому строка кода создает список имен столбцов. – Taryn

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