Я использую SQL Server 2017. Я пытаюсь вернуть набор данных с SQL Сервер в формате, который в конечном итоге go, в электронную таблицу Excel. Данные сложны, и хотя я мог бы вывести данные в виде двух наборов в Excel, а затем использовать код для создания VLOOKUP
для объединения наборов данных, я стараюсь избежать этого дополнительного осложнения.
Проще говоря, у меня есть набор оценок для студентов за курсы, которые они прошли. Таблица может выглядеть примерно так:
CREATE TABLE TempStudentMarks
(
StudentID VARCHAR(4),
CourseName VARCHAR(50),
Mark INT
)
INSERT INTO TempStudentMarks (StudentID, CourseName, Mark)
VALUES ('1234', 'English', 78),
('1234', 'Maths', 68),
('1234', 'Science', 58),
('4321', 'English', 66),
('4321', 'Maths', 76),
('4321', 'French', 86),
('5555', 'Maths', 69),
('5555', 'Science', 49),
('5555', 'French', 69),
('6666', 'English', 33),
('6666', 'Maths', 44),
('6666', 'Science', 55),
('6666', 'French', 66)
Я создал хранимую процедуру, которая выводит каждого студента в строке, а каждый курс в столбце. Он использует динамический c SQL, потому что количество курсов варьируется в зависимости от года и зависит от ряда других факторов:
CREATE PROCEDURE spTemp_StudentMarksPivot
AS
DECLARE @SQL NVARCHAR(MAX)
DECLARE @PivotCols NVARCHAR(MAX)
SELECT
@PivotCols = COALESCE(@PivotCols + ',', '') +
QUOTENAME(CourseName)
FROM
(SELECT DISTINCT CourseName
FROM TempStudentMarks) AS HeaderData
PRINT @PivotCols
SET @SQL = 'SELECT StudentID, ' + @PivotCols + '
FROM (SELECT * FROM TempStudentMarks) SourceData
PIVOT (MAX(Mark) FOR CourseName IN (' + @PivotCols + ')) AS PivotData'
PRINT @SQL
EXEC sys.sp_executesql @SQL
Это работает достаточно хорошо; вывод, который я получаю для этого:
EXEC spTemp_StudentMarksPivot
выглядит так:
StudentID English French Maths Science
--------- ----------- ----------- ----------- -----------
1234 78 NULL 68 58
4321 66 86 76 NULL
5555 NULL 69 69 49
6666 33 66 44 55
У меня также есть представление, которое выполняет некоторый статистический анализ. Упрощенная версия выглядит следующим образом:
CREATE VIEW vwStudentAggregates
AS
SELECT tsm.StudentID, AVG(Mark) AS Average, MAX(Mark) AS BestMark
FROM TempStudentMarks tsm
GROUP BY tsm.StudentID
Когда я запускаю оператор SELECT
для этого представления, я получаю следующее:
StudentID Average BestMark
--------- ----------- -----------
1234 68 78
4321 76 86
5555 62 69
6666 49 66
Все это хорошо.
Но у меня вопрос об объединении двух, чтобы получить результат, подобный следующему:
StudentID English French Maths Science Average BestMark
--------- ----------- ----------- ----------- ----------- ---------- ----------
1234 78 NULL 68 58 68 78
4321 66 86 76 NULL 76 76
5555 NULL 69 69 49 62 69
6666 33 66 44 55 49 66
Возможно ли это?
Я не могу понять, как я могу создать временную таблицу, учитывая, что я заранее не знаю числа или имен столбцов. Я посмотрел на решение здесь:
Вставьте результаты хранимой процедуры во временную таблицу
И хотя я думал, что это может сделать работу, ситуация осложняется тем, что некоторые пользователи входят в систему через Windows аутентификацию, в то время как другие должны использовать SQL аутентификацию, поэтому, хотя это решение использует OpenRowset, я опускаюсь на бит, который говорит
SELECT *
INTO #MyTempTable
FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC getBusinessLineHistory')
потому что я не знаю, как создать строку подключения, которая будет работать для всех.
[Редактировать] Я просто немного поигрался с этой идеей и получил целый ряд ошибок, начиная с
"Процедура sp_configure, строка 105 Пользователь не имеет разрешения выполнить это действие. "
и заканчивая
"SQL Сервер заблокировал доступ к ЗАЯВЛЕНИЮ 'OpenRowset / OpenDatasource"
, так что это не выглядит хорошо ... (эта работа для клиента где отдел ИКТ довольно ограничен в вопросах безопасности и вряд ли захочет предоставить дополнительные разрешения ...
Если кто-то может помочь или направить, я был бы очень благодарен.
Большое спасибо Andrew