2015-11-05 2 views
2

У меня есть таблица с результатами, как это:Динамическая шарнирные несколько столбцов

EMP_ID | Boss_ID | Boss_Name | Specialty 

    1001  001  John    sql 
    1001  001  John    c# 
    1002  002  James   c++ 
    1002  003  Sarah   sql 
    1002  003  Sarah   python 
    1003  004  Jesse   networking 

Сотрудники могут иметь несколько боссов, которые могут иметь несколько специальностей.

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

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

Вот что у меня есть:

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

    select t.EMP_ID 
     ,t.Boss_Name 
     ,t.Boss_ID 
     ,t.Specialty 
     ,'BOSS' + '_' + cast(ROW_NUMBER() OVER (PARTITION BY t.EMP_ID ORDER BY t.BOSS_ID asc) AS VARCHAR) AS b_rn 
     ,'SPEC' + '_' + cast(ROW_NUMBER() OVER (PARTITION BY t.Specialty ORDER BY t.BOSS_ID asc) AS VARCHAR) AS spec_rn 
    INTO #work 
    from #testing t 

SELECT @cols = STUFF(
        (SELECT DISTINCT TOP 100 PERCENT '],[' + w.b_rn 
        FROM #work w 
        ORDER BY '],[' + w.b_rn 
        FOR XML PATH('') 
       ), 1, 2, '' 
       ) + ']' 

PRINT @cols 

SET @query = N' SELECT EMP_ID,' + @cols + N' 
      INTO ##work_results FROM 
       (
        SELECT EMP_ID 
         ,Boss_Name 
         ,b_rn 

        FROM #work 
       ) AS sourcetable 
PIVOT 
(
max(Boss_Name) for b_rn IN ('+ @cols + N') 
) AS pivot_table' 


execute(@query) 

select * from ##work_results 

Это дает мне:

EMP_ID | BOSS_1 | BOSS_2 | BOSS_3 
1001  John  John   NULL 
1002  James  Sarah   Sarah 
1003  Jesse  NULL   NULL 

То, что я действительно ищет это результаты, как это:

EMP_ID | Boss_1 | Specialty_1 | Boss_2 | Specialty_1 

    1001  John  sql 
    1002  James c++   Sarah  sql 
    1003  Jesse networking 

Я смотрел другие сообщения, но они не совсем то, что я ищу.

Любая помощь будет замечательной.

Спасибо!

+0

Это одно из ограничений PIVOT. Он не может поворачивать несколько столбцов. Я предпочитаю использовать динамическую перекрестную вкладку даже с одним столбцом. Для меня синтаксис менее тупой, и он даже имеет небольшое преимущество в производительности. Вот замечательная статья, объясняющая, как это работает. http://www.sqlservercentral.com/articles/Crosstab/65048/ –

+0

Я прочитаю эту статью. Спасибо за ответ! – jw133

+0

Возможно, вы можете присоединиться к 'pivot_table' обратно к' # testing', чтобы получить специальность для каждого босса. Вы должны были бы присоединиться один раз для каждой колонки босса. –

ответ

0

Вы могли бы пойти по этому пути:

Хитрость заключается в том, чтобы конкатенировать ваши ценности. Поэтому только один столбец, никаких проблем с шарниром ...

DECLARE @tbl TABLE(EMP_ID INT,Boss_ID INT,Boss_Name VARCHAR(100),Specialty VARCHAR(100)); 
INSERT INTO @tbl VALUES 
(1001,001,'John','sql') 
,(1001,001,'John','c#') 
,(1002,002,'James','c++') 
,(1002,003,'Sarah','sql') 
,(1002,003,'Sarah','python') 
,(1003,004,'Jesse','networking'); 

SELECT p.* 
FROM 
(
    SELECT tbl.EMP_ID 
      --If you need your Bosses in the given order you must add a sort crit to your original table! 
      ,'Column_' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.EMP_ID ORDER BY tbl.EMP_ID) AS VARCHAR(MAX)) AS ColumnName 
      ,tbl.Boss_Name + ' (' + tbl.Specialty + ')' AS Concatenated 
    FROM @tbl AS tbl 
) AS ToBePivoted 
PIVOT 
(
    MIN(Concatenated) FOR ColumnName IN(Column_1,Column_2,Column_3 /*add maximum here*/) 
) As p 

Результат

1001 John (sql)   John (c#)  NULL 
1002 James (c++)   Sarah (sql) Sarah (python) 
1003 Jesse (networking) NULL   NULL 

Если вам нужны значения разделены еще один фокус в том, чтобы объединить все необходимые столбцы в XML-формате (но не XML-Type!).

Поскольку конкатенация представляет собой XML-формат, довольно просто извлечь элементы только через их индекс.

DECLARE @tbl TABLE(EMP_ID INT,Boss_ID INT,Boss_Name VARCHAR(100),Specialty VARCHAR(100)); 
INSERT INTO @tbl VALUES 
(1001,001,'John','sql') 
,(1001,001,'John','c#') 
,(1002,002,'James','c++') 
,(1002,003,'Sarah','sql') 
,(1002,003,'Sarah','python') 
,(1003,004,'Jesse','networking'); 

SELECT p.EMP_ID 

     ,CAST(Column_1 AS XML).value('x[1]','int') AS BossID_1 
     ,CAST(Column_1 AS XML).value('x[2]','varchar(max)') AS BossName_1 
     ,CAST(Column_1 AS XML).value('x[3]','varchar(max)') AS specialty_1 

     ,CAST(Column_2 AS XML).value('x[1]','int') AS BossID_2 
     ,CAST(Column_2 AS XML).value('x[2]','varchar(max)') AS BossName_2 
     ,CAST(Column_2 AS XML).value('x[3]','varchar(max)') AS specialty_2 

     ,CAST(Column_3 AS XML).value('x[1]','int') AS BossID_3 
     ,CAST(Column_3 AS XML).value('x[2]','varchar(max)') AS BossName_3 
     ,CAST(Column_3 AS XML).value('x[3]','varchar(max)') AS specialty_3 
     /*Add a maximum here*/ 
FROM 
(
    SELECT tbl.EMP_ID 
      --If you need your Bosses in the given order you must add a sort crit to your original table! 
      ,'Column_' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.EMP_ID ORDER BY tbl.EMP_ID) AS VARCHAR(MAX)) AS ColumnName 
      ,'<x>' + CAST(tbl.Boss_ID AS VARCHAR(10)) + '</x><x>' + tbl.Boss_Name + '</x><x>' + tbl.Specialty + '</x>' AS ValuesAsXML 
    FROM @tbl AS tbl 
) AS ToBePivoted 
PIVOT 
(
    MIN(ValuesAsXML) FOR ColumnName IN(Column_1,Column_2,Column_3 /*add maximum here*/) 
) As p 

Результат

1001 1 John sql   1  John c#  NULL NULL NULL 
1002 2 James c++   3  Sarah sql  3  Sarah python 
1003 4 Jesse networking NULL NULL NULL NULL NULL NULL 
+0

ha Сначала я попробовал метод concatenate, но конечный пользователь хочет специальность в своем столбце. Что касается вашего второго метода, это работает, но я знаю, сколько будет столбцов. Количество боссов является переменной, поэтому я не смог бы перечислять столбцы здесь. (извиняюсь, если я что-то пропустил) Спасибо! – jw133

+0

@ jw133, ладно, конечный пользователь - король ;-) А как насчет XML-трюка? – Shnugo

+0

oops, что должно было быть больше вопросом. Для трюка XML я немного запутался в том, как настроить его динамически.Пример, который вы опубликовали, отлично работает, но только если я знаю, сколько столбцов (в данном случае 3). – jw133

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