Хранимая процедура SQL, выводит строки в виде столбцов для сводки - PullRequest
0 голосов
/ 03 декабря 2011

Использование SQL 2005 Вот как выглядят мои результаты SQL

UserID | Frame | Choice | Description | DateTime
------------------------------------------------
bcn005 | PL_P03| 1      | Rules-Based | 2011-10-24 14:14:26
bcn005 | PL_P04| 0      | VirtueBased | 2011-10-24 14:16:37
...
bmk172 | Prac_1| 0      | None        | 2011-10-25 12:45:38
...

Мой клиент хочет, чтобы результаты выглядели так

UserID | Frame | Choice | Description | DateTime  | Frame | Choice | Description | DateTime 
-------------------------------------------------------------------------------------------
bcn005 | PL_P03| 1      | Rules-Based | 2011-10-..| PL_P04| 0      | VirtueBased | 2011-10-..
bmk172 | Prac_1| 0      | None        | 2011-10-..|

Где ответы всех участников находятся в одном ряду. В основном должен быть другой набор Frame / Choice Description / DateTime для каждой строки набора результатов.

Это результаты опроса, но это тип опроса, когда один участник мог вернуться и изменить свой ответ 5 раз. Таким образом, количество Frame / Choice Description / DateTime для каждого UserID будет разным.

Я знаю, что должен использовать хранимую процедуру (или, может быть, даже макрос Excel), но я совершенно новичок в обоих случаях. Любое руководство приветствуется. Вот мой SQL-запрос

select UserID, locationName AS 'Frame', student_response AS 'Choice',
description, DateTime
from tblStudentResponses
WHERE GroupID in (18,20,21,36,37,38,39,40)
AND UserID in (SELECT UserID FROM tblStudentResponses WHERE
locationName = 'Character1Certificate')
AND DateTime > '2011-10-01'
AND type = 'choice'
order by UserID

<ч /> !! ОБНОВЛЕНИЕ !! Полное рабочее решение и тестовый код <ч /> - Пример подготовки данных ЗАЯВИТЬ @FrameChoices as TABLE (UserId varchar (50), Frame varchar (50), Choice varchar (4000), Описание varchar (1000), [DateTime] DateTime)

--Test Values
INSERT INTO @FrameChoices(UserId,Frame,Choice,Description,[DateTime])
SELECT  UserId,Frame,Choice,Description,[DateTime]
FROM (
    SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, '1' AS Choice, 'Rules-Based'
    AS Description, '2011-10-24 14:14:26' AS [DateTime]
    UNION ALL
    SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, '0' AS Choice, 'VirtueBased'
    AS Description, '2011-10-24 14:16:37' AS [DateTime]
    UNION ALL
    SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, '0' AS Choice, 'None' AS
    Description, '2011-10-25 12:45:38' AS [DateTime]
) T

- Подготовка динамического SQL

DECLARE @SQL VARCHAR(MAX)
DECLARE @MaxNumberOfFrames INT

SET @SQL = ''
SET @MaxNumberOfFrames = 1

SELECT @MaxNumberOfFrames = MAX(FrameCount)
  FROM
    (
        SELECT COUNT(1) FrameCount
        FROM @FrameChoices
        GROUP BY UserId  
    ) T

 --needed to be part of the SQL string to EXEC at the bottom
SET @SQL = 'DECLARE @FrameChoices as TABLE(UserId varchar(50),Frame varchar(50),Choice varchar(4000),Description varchar(1000),[DateTime] DateTime)' 

SET @SQL = @SQL + ' INSERT INTO @FrameChoices(UserId,Frame,Choice,Description,[DateTime])'
SET @SQL = @SQL + ' SELECT  UserId,Frame,Choice,Description,[DateTime]'
SET @SQL = @SQL + ' FROM ('
SET @SQL = @SQL + '     SELECT ''bcn005'' AS UserId, ''PL_P03'' AS Frame, ''1'' AS Choice, ''Rules-Based'''
SET @SQL = @SQL + '     AS Description, ''2011-10-24 14:14:26'' AS [DateTime]'
SET @SQL = @SQL + '     UNION ALL'
SET @SQL = @SQL + '     SELECT ''bcn005'' AS UserId, ''PL_P04'' AS Frame, ''0'' AS Choice, ''VirtueBased'''
SET @SQL = @SQL + '     AS Description, ''2011-10-24 14:16:37'' AS [DateTime]'
SET @SQL = @SQL + '     UNION ALL'
SET @SQL = @SQL + '     SELECT ''bmk172'' AS UserId, ''Prac_1'' AS Frame, ''0'' AS Choice, ''None'' AS'
SET @SQL = @SQL + '     Description, ''2011-10-25 12:45:38'' AS [DateTime]'
SET @SQL = @SQL + ' ) T'

SET @SQL = @SQL + ' SELECT UserId'

--changed size to max
DECLARE @ColumnSQL VARCHAR(MAX)
DECLARE @CurrentFrame INT

SET @CurrentFrame = 1

WHILE (@CurrentFrame <= @MaxNumberOfFrames)
BEGIN
    SET @ColumnSQL = ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Frame ELSE '''' END) AS Frame_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Choice ELSE '''' END) AS Choice_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Description ELSE '''' END) AS Description_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN [DateTime] ELSE NULL END) AS DateTime_'+CAST(@CurrentFrame AS VARCHAR)
    SET @SQL = @SQL + @ColumnSQL
    SET @CurrentFrame = @CurrentFrame + 1
END

SET @SQL = @SQL + ' FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM @FrameChoices) T GROUP BY T.UserId'

PRINT @SQL

- этот сгенерированный SQL затем может быть выполнен с помощью

EXEC(@SQL)
 -- OR
EXEC SP_EXECUTESQL(@SQL)

- Образец SQL, сгенерированный из вышеприведенного запроса

DECLARE @FrameChoices as TABLE(UserId varchar(50),Frame varchar(50),Choice varchar(4000),Description varchar(1000),[DateTime] DateTime) INSERT INTO @FrameChoices(UserId,Frame,Choice,Description,[DateTime]) SELECT  UserId,Frame,Choice,Description,[DateTime] FROM (     SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, '1' AS Choice, 'Rules-Based'  AS Description, '2011-10-24 14:14:26' AS [DateTime]     UNION ALL   SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, '0' AS Choice, 'VirtueBased'  AS Description, '2011-10-24 14:16:37' AS [DateTime]     UNION ALL   SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, '0' AS Choice, 'None' AS  Description, '2011-10-25 12:45:38' AS [DateTime] ) T SELECT UserId, MAX(CASE WHEN RowNumber =1 THEN Frame ELSE '' END) AS Frame_1, MAX(CASE WHEN RowNumber =1 THEN Choice ELSE '' END) AS Choice_1, MAX(CASE WHEN RowNumber =1 THEN Description ELSE '' END) AS Description_1, MAX(CASE WHEN RowNumber =1 THEN [DateTime] ELSE NULL END) AS DateTime_1, MAX(CASE WHEN RowNumber =2 THEN Frame ELSE '' END) AS Frame_2, MAX(CASE WHEN RowNumber =2 THEN Choice ELSE '' END) AS Choice_2, MAX(CASE WHEN RowNumber =2 THEN Description ELSE '' END) AS Description_2, MAX(CASE WHEN RowNumber =2 THEN [DateTime] ELSE NULL END) AS DateTime_2 FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM @FrameChoices) T GROUP BY T.UserId

Ответы [ 2 ]

1 голос
/ 03 декабря 2011

Если SQL 2005 или ABove, вы можете попробовать pivot.

Если SQL 2000, используйте комбинацию Group By и Case.

SELECT GC1,
       GC2,
       MAX(CASE WHEN CONDITION1 THEN Value1 ELSE Value2 END) AS DerivedColumn
FROM Table1
GROUP BY GC1, GC2

Ссылка: SQL Server PIVOT и UNPIVOT

Шарнир с динамической колонной

Вопрос о переполнении стека

[Решение]

- Подготовка данных образца

DECLARE @FrameChoices TABLE
(
  UserId varchar(20),
  Frame varchar(20),
  Choice int,
  Description varchar(20),
  [DateTime] DateTime
)

INSERT INTO @FrameChoices(UserId,Frame,Choice,Description,[DateTime])
SELECT  UserId,Frame,Choice,Description,[DateTime]
  FROM (
        SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, 1 AS Choice, 'Rules-Based' AS Description, '2011-10-24 14:14:26' AS [DateTime]
        UNION ALL
        SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, 0 AS Choice, 'VirtueBased' AS Description, '2011-10-24 14:16:37' AS [DateTime]
        UNION ALL
        SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, 0 AS Choice, 'None' AS Description, '2011-10-25 12:45:38' AS [DateTime]
       ) T

- Подготовка динамического SQL

DECLARE @SQL VARCHAR(4000)
DECLARE @MaxNumberOfFrames INT

SET @SQL = ''
SET @MaxNumberOfFrames = 1

SELECT @MaxNumberOfFrames = MAX(FrameCount)
  FROM
(
SELECT COUNT(1)FrameCount
  FROM @FrameChoices
 GROUP BY UserId  
) T

SET @SQL = 'SELECT UserId'

DECLARE @ColumnSQL VARCHAR(512)
DECLARE @CurrentFrame INT

SET @CurrentFrame = 1

WHILE (@CurrentFrame <= @MaxNumberOfFrames)
BEGIN
    SET @ColumnSQL = ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Frame ELSE NULL END) AS Frame_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Choice ELSE NULL END) AS Choice_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN Description ELSE NULL END) AS Description_'+CAST(@CurrentFrame AS VARCHAR)
                    + ', MAX(CASE WHEN RowNumber ='+CAST(@CurrentFrame AS VARCHAR)+ ' THEN [DateTime] ELSE NULL END) AS DateTime_'+CAST(@CurrentFrame AS VARCHAR)
    SET @SQL = @SQL + @ColumnSQL
    SET @CurrentFrame = @CurrentFrame + 1
END

SET @SQL = @SQL + ' FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM @FrameChoices) T GROUP BY T.UserId'

PRINT @SQL

- этот сгенерированный SQL затем может быть выполнен с помощью

EXEC(@SQL)
 -- OR
EXEC SP_EXECUTESQL(@SQL)

- Пример SQL, сгенерированный из вышеприведенного запроса

SELECT UserId, MAX(CASE WHEN RowNumber =1 THEN Frame ELSE NULL END) AS Frame_1, MAX(CASE WHEN RowNumber =1 THEN Choice ELSE NULL END) AS Choice_1, MAX(CASE WHEN RowNumber =1 THEN Description ELSE NULL END) AS Description_1, MAX(CASE WHEN RowNumber =1 THEN [DateTime] ELSE NULL END) AS DateTime_1, MAX(CASE WHEN RowNumber =2 THEN Frame ELSE NULL END) AS Frame_2, MAX(CASE WHEN RowNumber =2 THEN Choice ELSE NULL END) AS Choice_2, MAX(CASE WHEN RowNumber =2 THEN Description ELSE NULL END) AS Description_2, MAX(CASE WHEN RowNumber =2 THEN [DateTime] ELSE NULL END) AS DateTime_2 FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM @FrameChoices) T GROUP BY T.UserId
0 голосов
/ 03 декабря 2011

То, что вы хотите, это функциональность сводной таблицы SQL Server

http://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx

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