Выделить значения столбца в столбцы, используя опоры


У меня есть сценарий, в котором я хочу отобразить значения столбцов(Val1) для каждого уникального значения столбца (Val2) в виде отдельного столбца с максимальным числом столбцов 10.

CREATE TABLE #TEMP1 (Val1 NVARCHAR(4), Val2 NVARCHAR(10));

insert into #Temp1 Values ('S01','00731')
insert into #Temp1 Values ('S02','00731')
insert into #Temp1 Values ('S03','00731')
insert into #Temp1 Values ('S04','00731')
insert into #Temp1 Values ('S05','00731')
insert into #Temp1 Values ('S06','00731')
insert into #Temp1 Values ('S07','00731')
insert into #Temp1 Values ('S08','00731')
insert into #Temp1 Values ('S09','00731')
insert into #Temp1 Values ('S07','00731')
insert into #Temp1 Values ('S04','00741')
insert into #Temp1 Values ('S01','00746')
insert into #Temp1 Values ('S01','00770')
insert into #Temp1 Values ('S01','00771')
insert into #Temp1 Values ('S02','00771')

Val1    Val2
--------------------------
S01     00731
S02     00731
S03     00731
S04     00731
S05     00731
S06     00731
S07     00731
S08     00731
S09     00731
S07     00731
S04     00741
S01     00746
S01     00770
S01     00771
S02     00771

Затем я использую сводный столбец, чтобы показать каждое уникальное значение Val2 и максимум 10 значений Val1 в качестве столбцов.

SELECT [Val2],
c1, c2, c3, c4, c5, c6, c7, c8, c9, c10
FROM
(SELECT Val1, Val2
FROM         #TEMP1) AS PivotTable
PIVOT
(
MAX([PivotTable].[Val1])
FOR
Val1
IN
(C1, c2, c3, c4, c5, c6, c7, c8, c9, c10)
) AS PivotTable;

Я хочу иметь такие результаты, как:

Val2    c1  c2  c3  c4  c5  c6  c7  c8  c9  c10
--------------------------------------------------------------------------------------
00731  S01  S02 S03 S04 S05 S06 S07 S08 S09 S07 
00741  S04  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00746  S01  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00770  S01  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00771  S01  S02 NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

Но на самом деле я просто получаю все нулевые значения для столбцов:

Val2    c1  c2  c3  c4  c5  c6  c7  c8  c9  c10
--------------------------------------------------------------------------------------
00731  NULL NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00741  NULL NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00746  NULL NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00770  NULL NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
00771  NULL NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
2 3

2 ответа:

Ваши требования не совсем ясны, но похоже, что вы пытаетесь создать новый столбец с именем c, а затем row_number(), связанный с ним - c1, c2 c3, etc.

Если бы вы использовали в своем подзапросе следующее:

SELECT Val1, Val2,
  'C'+ cast(row_number() over(partition by Val2 
                              order by val1) as varchar(10)) col
FROM TEMP1

Смотрите SQL Fiddle with Demo

Вы получите результат:

| VAL1 |  VAL2 | COL |
----------------------
|  S01 | 00731 |  C1 |
|  S02 | 00731 |  C2 |
|  S03 | 00731 |  C3 |
|  S04 | 00731 |  C4 |
|  S05 | 00731 |  C5 |
|  S06 | 00731 |  C6 |
|  S07 | 00731 |  C7 |
|  S07 | 00731 |  C8 |
|  S08 | 00731 |  C9 |
|  S09 | 00731 | C10 |
|  S04 | 00741 |  C1 |
|  S01 | 00746 |  C1 |
|  S01 | 00770 |  C1 |
|  S01 | 00771 |  C1 |
|  S02 | 00771 |  C2 |

Который, кажется, является результатом, который вы затем хотите PIVOT. Затем вы примените PIVOT к этому, используя:

SELECT Val2,
   c1, c2, c3, c4, c5, c6, c7, c8, c9, c10
FROM
(
  SELECT Val1, Val2,
    'C'+ cast(row_number() over(partition by Val2 
                                order by val1) as varchar(10)) col
  FROM TEMP1
) src
PIVOT
(
  MAX(Val1)
  FOR col IN (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)
) piv;

См. SQL Fiddle with Демо . Ваш окончательный результат тогда:

|  VAL2 |  C1 |     C2 |     C3 |     C4 |     C5 |     C6 |     C7 |     C8 |     C9 |    C10 |
------------------------------------------------------------------------------------------------
| 00731 | S01 |    S02 |    S03 |    S04 |    S05 |    S06 |    S07 |    S07 |    S08 |    S09 |
| 00741 | S04 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00746 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00770 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00771 | S01 |    S02 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
Примечание: мои результаты немного отличаются от того, что вы запрашиваете в качестве желаемого результата, потому что я выполняю ORDER BY val1, который заставляет значения S07 группироваться вместе.

Нет никакого порядка данных в базе данных, если вы не запросите его, поэтому нет никакой гарантии, что одно из значений S07 будет выглядеть как C10. Вы можете использовать следующее, Чтобы получить результат, но нет никакой гарантии , что результат всегда будет в правильном порядке:

SELECT Val2,
  c1, c2, c3, c4, c5, c6, c7, c8, c9, c10
FROM
(
  SELECT Val1, Val2,
    'C'+ cast(row_number() over(partition by Val2 
                                order by (select 1)) as varchar(10)) col
  FROM TEMP1
) src
PIVOT
(
  MAX(Val1)
  FOR col IN (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)
) piv;

Смотрите SQL Fiddle with Demo. Использование order by (select 1) изменяет порядок данных, но не гарантирует, что он всегда будет в этом порядке. В результате получается:

|  VAL2 |  C1 |     C2 |     C3 |     C4 |     C5 |     C6 |     C7 |     C8 |     C9 |    C10 |
------------------------------------------------------------------------------------------------
| 00731 | S01 |    S02 |    S03 |    S04 |    S05 |    S06 |    S07 |    S08 |    S09 |    S07 |
| 00741 | S04 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00746 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00770 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 00771 | S01 |    S02 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |

Вы можете попробовать стандартный способ создания кросс-табуляции или пивота с помощью коррелированных подзапросов и использовать функцию ранжирования (здесь в CTE), чтобы определить, в какой столбец поместить ваши значения:

;with cte as (
    select Val1
        , Val2
        , row_number() over (partition by Val2 order by Val1) as col
        --, row_number() over (partition by Val2 order by Id) as col -- Use this if you have an identity
    from #TEMP1
    --from (select distinct * from #TEMP1) as t -- Use this to rank distinct entries
)
select c.Val2
    , (select Val1 from cte where Val2 = c.Val2 and col = 1) as c1
    , (select Val1 from cte where Val2 = c.Val2 and col = 2) as c2
    , (select Val1 from cte where Val2 = c.Val2 and col = 3) as c3
    , (select Val1 from cte where Val2 = c.Val2 and col = 4) as c4
    , (select Val1 from cte where Val2 = c.Val2 and col = 5) as c5
    , (select Val1 from cte where Val2 = c.Val2 and col = 6) as c6
    , (select Val1 from cte where Val2 = c.Val2 and col = 7) as c7
    , (select Val1 from cte where Val2 = c.Val2 and col = 8) as c8
    , (select Val1 from cte where Val2 = c.Val2 and col = 9) as c9
    , (select Val1 from cte where Val2 = c.Val2 and col = 10) as c10
from cte as c
group by c.Val2
order by c.Val2
Обратите внимание, что есть несколько способов определить, какой столбец Val2 принадлежит, и я предложил пару возможностей в CTE (некоторые прокомментированы). Тем не менее, ваш текущий желаемый выход невозможно достичь, так как в настоящее время нет способа сказать, что S07 должен быть в десятом колонка. Возможно, добавление идентификатора во временную таблицу будет отражать порядок событий, если вы этого хотите. Я также включил эту возможность в CTE.