2014-01-23 9 views
2

То, что я считал довольно простым, кажется, немного сложнее, чем я ожидал.PIVOT динамически, возвращенные результаты из JOIN из двух таблиц

У меня есть две таблицы. С отношением «один ко многим». То, что я пытаюсь сделать, - это любая запись, возвращаемая таблицей 2. Я хочу, чтобы она была в отдельном столбце. Мне удалось сделать это в следующем запросе с относительными небольшими данными и узнать, что возвращается второй таблицей.

Примеры данных

DECLARE @TABLE1 TABLE(UserID INT,Episode INT ,[Value] VARCHAR(100)) 
INSERT INTO @TABLE1 VALUES 
(1, 1,'VALUE 1-1'),(1, 2,'VALUE 1-2') 

DECLARE @TABLE2 TABLE(UserID INT,Episode INT ,[Details] VARCHAR(100)) 
INSERT INTO @TABLE2 VALUES 
(1, 1,'Details 1'),(1, 1,'Details 2'),(1, 2,'Details 1'),(1, 2,'Details 2') 

Простой Регистрация

SELECT ONE.UserID 
     , ONE.Episode 
     , ONE.Value 
     , TWO.Details 
FROM @TABLE1 ONE INNER JOIN @TABLE2 Two 
ON ONE.UserID = TWO.UserID 
AND ONE.Episode = TWO.Episode 

╔════════╦═════════╦═══════════╦═══════════╗ 
║ UserID ║ Episode ║ Value ║ Details ║ 
╠════════╬═════════╬═══════════╬═══════════╣ 
║  1 ║  1 ║ VALUE 1-1 ║ Details 1 ║ 
║  1 ║  1 ║ VALUE 1-1 ║ Details 2 ║ 
║  1 ║  2 ║ VALUE 1-2 ║ Details 1 ║ 
║  1 ║  2 ║ VALUE 1-2 ║ Details 2 ║ 
╚════════╩═════════╩═══════════╩═══════════╝ 

В этом случае я хотел бы PIVOT Описание столбцов. Что мне удалось сделать с довольно простой PIVOT запрос следующим образом

PIVOT Запрос

SELECT * FROM 
(
SELECT ONE.UserID 
     , ONE.Episode 
     , ONE.Value 
     , TWO.Details 
FROM @TABLE1 ONE INNER JOIN @TABLE2 Two 
ON ONE.UserID = TWO.UserID AND ONE.Episode = TWO.Episode)Q 
PIVOT (MAX(Details) 
     FOR Details 
     IN ([Details 1], [Details 2]))p 

╔════════╦═════════╦═══════════╦═══════════╦═══════════╗ 
║ UserID ║ Episode ║ Value ║ Details 1 ║ Details 2 ║ 
╠════════╬═════════╬═══════════╬═══════════╬═══════════╣ 
║  1 ║  1 ║ VALUE 1-1 ║ Details 1 ║ Details 2 ║ 
║  1 ║  2 ║ VALUE 1-2 ║ Details 1 ║ Details 2 ║ 
╚════════╩═════════╩═══════════╩═══════════╩═══════════╝ 

Это именно то, что я хочу, все записи возвращаются из таблицы два в Колонном Названный как Details 1, Details 2 и Details 3 и т. Д.

В этом случае это сработало, потому что данные, перенастроенные сами по себе, являются строками как «Детали 1», «Детали 2» и «Детали 3».

Но когда я не знаю, сколько строк будет возвращено из таблицы2, и какими будут данные, с которыми я борюсь, чтобы развернуть это.

также еще одна важная вещь состоит в том, что данные, возвращаемые из таблицы 2, составляют Large Text values, состоящий из нескольких столбцов, объединенных.

Я пытался следовать логике, приведенной в this, this и this вопросы, но не радость.

Любая помощь любой указатель в правильном направлении очень ценится, спасибо заранее.

+0

Вам придется написать Dynamic SQL для обработки этого случая в SQL. –

+0

Весь вопрос. Я видел, где люди использовали динамический sql для достижения этого результата, динамический sql зависит от данных, перенастроенных из объединения. В моем случае данные возвращаются, это длинное текстовое значение can not действительно думает о том, как использовать этот возвращенный текст в my pivot query: S –

+0

Если вы не хотите использовать длинный текст в качестве имени столбца, какие имена столбцов вы хотите использовать? Просто что-то генерируется, как 'col1',' col2'? – FrankPl

ответ

6

Возможно, мне что-то не хватает, но вы должны иметь возможность PIVOT данных, но вам нужно будет реализовать row_number(), чтобы помочь генерировать столбцы.

Ключ будет использовать запрос, подобный:

SELECT ONE.UserID, 
    ONE.Episode, 
    ONE.Value, 
    TWO.Details, 
    'Details' 
    +cast(row_number() over(partition by one.userid, one.episode 
          order by two.details) as varchar(10)) seq 
FROM TABLE1 ONE 
INNER JOIN TABLE2 Two 
    ON ONE.UserID = TWO.UserID 
AND ONE.Episode = TWO.Episode 

Это создаст уникальную последовательность для новых имен столбцов, то вы можете применить PIVOT:

select userid, episode, 
    value, 
    details1, 
    details2 
from 
(
    SELECT ONE.UserID, 
    ONE.Episode, 
    ONE.Value, 
    TWO.Details, 
    'Details' 
     +cast(row_number() over(partition by one.userid, one.episode 
           order by two.details) as varchar(10)) seq 
    FROM TABLE1 ONE 
    INNER JOIN TABLE2 Two 
    ON ONE.UserID = TWO.UserID 
    AND ONE.Episode = TWO.Episode 
) d 
pivot 
(
    max(details) 
    for seq in (Details1, Details2) 
) piv; 

См SQL Fiddle with Demo , Затем вы можете преобразовать это динамический SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME('Details'+cast(seq as varchar(10))) 
        from 
        (
         select 
         row_number() over(partition by one.userid, one.episode 
               order by two.details) seq 
         FROM TABLE1 ONE 
         INNER JOIN TABLE2 Two 
          ON ONE.UserID = TWO.UserID 
         AND ONE.Episode = TWO.Episode 
        ) d 
        group by seq 
        order by seq 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT userid, episode, value, ' + @cols + ' 
      from 
      (
      SELECT ONE.UserID, 
       ONE.Episode, 
       ONE.Value, 
       TWO.Details, 
       ''Details'' 
        +cast(row_number() over(partition by one.userid, one.episode 
              order by two.details) as varchar(10)) seq 
       FROM TABLE1 ONE 
       INNER JOIN TABLE2 Two 
       ON ONE.UserID = TWO.UserID 
       AND ONE.Episode = TWO.Episode 
      ) x 
      pivot 
      (
       max(details) 
       for seq in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

См SQL Fiddle with Demo.Давая вам результат:

| USERID | EPISODE |  VALUE | DETAILS1 | DETAILS2 | 
|--------|---------|-----------|-----------|-----------| 
|  1 |  1 | VALUE 1-1 | Details 1 | Details 2 | 
|  1 |  2 | VALUE 1-2 | Details 1 | Details 2 | 
+0

Спасибо, миллион bluefeet, что вы суперзвезда :) –

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