我想成为一个好的网友并尽可能简单地解释我的问题 这是一些示例代码,我想说明一下。动态SQL返回我需要查看的结果,但在我可用的工具中,我有文本大小和功能限制。
实际上,我想将Dynamic SQL包装成CTE,参数化视图或存储过程,这样我就可以说SELECT * FROM GetStudentCourseCompletionByProgram('2')或EXEC GetStudentCourseCompletionByProgram('2')来获得动态结果我需要,但我不知道如何到达那里。如果需要,我可以删除它的“动态”方面,并硬编码返回10个COURSE列(总共12个),并假设没有程序将与10个以上的课程相关联。
感谢您提供任何帮助!
USE [tempdb]
GO
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'STUDENTS') DROP TABLE STUDENTS
CREATE TABLE STUDENTS ( ID INT PRIMARY KEY, NAME VARCHAR(50))
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'PROGRAMS') DROP TABLE PROGRAMS
CREATE TABLE PROGRAMS ( ID INT PRIMARY KEY, NAME VARCHAR(50))
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'COURSES') DROP TABLE COURSES
CREATE TABLE COURSES (ID INT PRIMARY KEY, NAME VARCHAR(50))
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'STUPROGRAMS') DROP TABLE STUPROGRAMS
CREATE TABLE STUPROGRAMS (ID INT PRIMARY KEY, STUDENT_ID INT, PROGRAM_ID INT)
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'PROGCOURSES') DROP TABLE PROGCOURSES
CREATE TABLE PROGCOURSES (ID INT PRIMARY KEY, PROGRAM_ID INT, COURSE_ID INT)
IF EXISTS (SELECT 1 FROM SYS.tables WHERE name = 'ENROLLMENTS') DROP TABLE ENROLLMENTS
CREATE TABLE ENROLLMENTS (ID INT PRIMARY KEY, STUDENT_ID INT, COURSE_ID INT)
INSERT INTO STUDENTS VALUES (1,'Caimbul'),(2,'Quassnoi'),(3,'Zohar'),(4,'Mike K'),(5,'Jeff');
INSERT INTO PROGRAMS VALUES (1,'Program1'),(2,'Program2');
INSERT INTO COURSES VALUES (1,'Course1'),(2,'Course2'),(3,'Course3'),(4,'Course4'),(5,'Course5');
INSERT INTO STUPROGRAMS VALUES (1,1,1),(2,2,1),(3,3,1),(4,4,1),(5,1,2),(6,2,2),(7,5,2);
INSERT INTO PROGCOURSES VALUES (1,1,1),(2,1,2),(3,1,3),(4,2,1),(5,2,3),(6,2,4),(7,2,5);
INSERT INTO ENROLLMENTS VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(7,2,2),(8,2,3),(11,3,1),(12,3,2),(14,3,4),(16,4,1),(18,4,3),(19,4,4),(23,5,3),(25,5,5);
-- Dynamic PIVOT Gives me the results I want.
--But I need it in a contained CTE Select query with a Program_ID parameter, or a Stored Procedure (with P.ID Param)
DECLARE @T AS TABLE(y INT NOT NULL PRIMARY KEY);
DECLARE
@cols AS NVARCHAR(MAX),
@y AS INT,
@sql AS NVARCHAR(MAX);
-- Construct the column list for the IN clause
SET @cols = STUFF(
(SELECT N',' + QUOTENAME(y) AS [text()]
FROM (SELECT C.ID AS Y FROM PROGCOURSES PC JOIN COURSES C ON PC.COURSE_ID=C.ID WHERE PC.PROGRAM_ID = '2' ) AS Y
ORDER BY y FOR XML PATH('')),1, 1, N'');
-- Construct the full T-SQL statement
-- and execute dynamically
SET @sql = N'SELECT * FROM
(SELECT S.NAME, S.ID AS StudentID, PC.COURSE_ID, E.ID
FROM STUPROGRAMS SP JOIN STUDENTS S ON SP.STUDENT_ID = S.ID
JOIN PROGRAMS P ON SP.PROGRAM_ID = P.ID
JOIN PROGCOURSES PC ON SP.PROGRAM_ID = PC.PROGRAM_ID
OUTER APPLY (
SELECT TOP 1 INE.*, C.NAME
FROM COURSES C
LEFT JOIN ENROLLMENTS INE ON C.ID = INE.COURSE_ID AND INE.STUDENT_ID = S.ID
WHERE PC.COURSE_ID = C.ID
ORDER BY INE.ID DESC) AS E
WHERE P.ID = ''2'') SOURCE
PIVOT (
COUNT(SOURCE.ID)
FOR COURSE_ID IN (' + @cols + N') ) AS PIV
ORDER BY NAME;';
EXEC sp_executesql @sql;
GO
删除了我之前的编辑/解释。
答案 0 :(得分:0)
嗯,这似乎有效:
SET QUOTED_IDENTIFIER, ANSI_NULLS ON
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.GetStudentCourseCompletionByProgram') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
DROP PROCEDURE dbo.GetStudentCourseCompletionByProgram
GO
CREATE PROC dbo.GetStudentCourseCompletionByProgram (@program INT)
AS
DECLARE
@cols NVARCHAR(MAX),
@y INT,
@sql NVARCHAR(MAX);
-- Construct the column list for the IN clause
SET @cols = STUFF(
(SELECT N',' + QUOTENAME(y) AS [text()]
FROM (SELECT C.ID AS Y
FROM PROGCOURSES PC
JOIN COURSES C ON PC.COURSE_ID=C.ID
WHERE PC.PROGRAM_ID = @program ) AS Y
ORDER BY y
FOR XML PATH('')),1, 1, N'');
-- Construct the full T-SQL statement
-- and execute dynamically
SET @sql = N'SELECT * FROM
(SELECT S.NAME, S.ID AS StudentID, PC.COURSE_ID, E.ID
FROM STUPROGRAMS SP JOIN STUDENTS S ON SP.STUDENT_ID = S.ID
JOIN PROGRAMS P ON SP.PROGRAM_ID = P.ID
JOIN PROGCOURSES PC ON SP.PROGRAM_ID = PC.PROGRAM_ID
OUTER APPLY (
SELECT TOP 1 INE.*, C.NAME
FROM COURSES C
LEFT JOIN ENROLLMENTS INE ON C.ID = INE.COURSE_ID
AND INE.STUDENT_ID = S.ID
WHERE PC.COURSE_ID = C.ID
ORDER BY INE.ID DESC) AS E
WHERE P.ID =' + cast(@program as nvarchar) + ') SOURCE
PIVOT (
COUNT(SOURCE.ID)
FOR COURSE_ID IN (' + @cols + N') ) AS PIV
ORDER BY NAME;';
EXEC sp_executesql @sql;
GO
GRANT EXECUTE ON dbo.GetStudentCourseCompletionByProgram TO standard
然后使用EXEC GetStudentCourseCompletionByProgram 2
(或1
或任何您喜欢的内容)来调用它。