2014-12-11 5 views
0

Прошу прощения за мое невежество. Я просто не знаком с поворотными запросами AT ALL, и все примеры, которые я нахожу, кажутся примерно такими же прозрачными, как и грязь. У меня есть таблица, которая возвращает GroupName и ID Numbers.простой SQL Pivot Query

Для примера:

SELECT GroupName, IDnumber FROM do.Table_1 

Возвращает

GroupName    IDnumber 
1       8395 
1       A660 
1       8396 
1       A661 
2       8398 
2       A662 
2       8399 

То, что я хочу что-то больше, как это:

GroupName    ID1  ID2 ID3 ID4 
1      8395 A660 8396 A661 
2      8398 A662 8399 NULL 

Как я могу это сделать? Сводный запрос? Какой-то другой метод?

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

ответ

3

Да, вы можете сделать это с помощью PIVOT, но не в этой форме, вы должны сначала создать номер строки, чтобы использовать ее для форматирования данных так, как вы хотите. Что-то вроде этого:

WITH Ranked 
AS 
(
    SELECT GroupName, IDnumber, 
    ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN 
    FROM Table1 
) 
SELECT GroupName, 
    [1] AS ID1, [2] AS ID2, [3] AS ID3, [4] AS ID4 
FROM Ranked AS r 
PIVOT 
(
    MAX(IDnumber) 
    FOR RN IN([1], [2], [3], [4]) 
) AS p; 

Это даст вам:

| GROUPNAME | ID1 | ID2 | ID3 | ID4 | 
|-----------|------|------|------|--------| 
|   1 | 8395 | A660 | 8396 | A661 | 
|   2 | 8398 | A662 | 8399 | (null) | 

Если вы хотите сделать это динамически, а не писать номер строки по вручную в операторе таблицы pivot, вам нужно сделать это с помощью динамического SQL, somethi нг как:

DECLARE @cols AS NVARCHAR(MAX); 
DECLARE @colnames AS NVARCHAR(MAX); 
DECLARE @query AS NVARCHAR(MAX); 

SELECT @cols = STUFF((SELECT distinct ',' + 
         QUOTENAME(RN) 
         FROM 
       (
       SELECT ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN 
       FROM Table1 
       ) AS t 
         FOR XML PATH(''), TYPE 
        ).value('.', 'NVARCHAR(MAX)') 
         , 1, 1, ''); 

SELECT @colnames = STUFF((SELECT distinct ',' + 
         QUOTENAME(RN) + 'AS' + 
         QUOTENAME('ID' + CAST(RN AS NVARCHAR(5))) 
         FROM 
       (
       SELECT ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN 
       FROM Table1 
       ) AS t 
         FOR XML PATH(''), TYPE 
        ).value('.', 'NVARCHAR(MAX)') 
         , 1, 1, ''); 

SELECT @query = 'WITH Ranked 
        AS 
        (
        SELECT GroupName, IDnumber, 
        ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GroupName) AS RN 
        FROM Table1 
       ) 
        SELECT GroupName, ' + @colnames + 
        ' FROM Ranked AS r 
        PIVOT 
        (
        MAX(IDnumber) 
        FOR RN IN(' + @cols + ')' + 
        ') p'; 

execute(@query); 

Это должно дать вам тот же результат:

| GROUPNAME | ID1 | ID2 | ID3 | ID4 | 
|-----------|------|------|------|--------| 
|   1 | 8395 | A660 | 8396 | A661 | 
|   2 | 8398 | A662 | 8399 | (null) | 
+0

Хорошо, это работает фантастически! Он делает именно то, что я хочу сделать. Но я не могу его спасти. Когда я пытаюсь сохранить нединамическую версию в качестве представления, поэтому я могу повторно использовать ее для своего приложения, она отсекает первые три строки. Не могу понять, почему. Если я попытаюсь сохранить динамическую версию, это говорит о наличии проблемы с оператором DECLARE и не позволит мне ее сохранить. Спасибо за помощь. – Jeff

+0

@Jeff - Вы не можете использовать его в представлении. Вы можете сделать это в хранимой процедуре. Он должен работать нормально. –

+0

Хорошо, я понял это и работал в своем приложении. Спасибо! – Jeff

0

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

SELECT * INTO #TEMP 
FROM 
(
SELECT 1 GroupName,    '8395' IDnumber 
    UNION ALL 
SELECT 1,       'A660' 
    UNION ALL 
SELECT 1,       '8396' 
    UNION ALL 
SELECT 1,       'A661' 
    UNION ALL 
SELECT 2,       '8398' 
    UNION ALL 
SELECT 2,       'A662' 
    UNION ALL 
SELECT 2,       '8399' 
)TAB 

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

SELECT *, 
'ID' + CAST(ROW_NUMBER() OVER(PARTITION BY GroupName ORDER BY GROUPNAME) AS VARCHAR(10)) IDS 
INTO #NEWTABLE 
FROM #TEMP 

Выбор столбцов для поворота

DECLARE @cols NVARCHAR (MAX) 

SELECT @cols = COALESCE (@cols + ',[' + IDS + ']', 
      '[' + IDS + ']') 
      FROM (SELECT DISTINCT IDS FROM #NEWTABLE) PV 
      ORDER BY IDS 

Теперь стержень динамически

DECLARE @query NVARCHAR(MAX) 
SET @query = '   
       SELECT * FROM 
      (
       SELECT * FROM #NEWTABLE 
      ) x 
      PIVOT 
      (
       MAX(IDnumber) 
       FOR IDS IN (' + @cols + ') 
      ) p  

      '  
EXEC SP_EXECUTESQL @query 

Click here to view the result (упаковывают ошибка произошла на странице загрузки пресс RUNSQL, она работает)

РЕЗУЛЬТАТ

enter image description here

+0

Я обновил. Пожалуйста, проверьте. Его просто читать и понимать @Jeff –