从2结合返回表的存储过程

时间:2014-02-26 01:48:42

标签: sql sql-server-2008 stored-procedures cursor

我正在尝试编写一个存储过程,它返回一个结果,组合了两个表变量,看起来像这样。

Name | LastName | course | course | course  | course  <- Columns
Name | LastName | DVA123 | DVA222 | nothing | nothing <- Row1
Pete   Steven       200                               <- Row2    
Steve  Lastname              50                       <- Row3

从这3张表中

员工

Name | LastName | SSN |
Steve  Lastname   234 
Pete   Steven     132

课程实例

Course | Year | Period |
DVA123   2013     1 
DVA222   2014     2

出席

Course | SSN |  Year  | Period | Hours |
DVA123   234    2013      1       200 
DVA222   132    2014      2       50

我将@year作为参数,决定课程中哪一年会显示在结果中。

ALTER proc [dbo].[test4]
   @year int
as
begin

-- I then declare the 2 tables which I will then store the values from the tables
DECLARE @Table1 TABLE( 
   Firstname varchar(30) NOT NULL, 
   Lastname varchar(30) NOT NULL 
); 

DECLARE @Table2 TABLE( 
   Course varchar(30) NULL
);

声明@variable varchar(max) - 用于保存游标值的变量,然后将course1设置为4

我想要最高的4个结果/课程实例,我稍后在一年中订购

declare myCursor1 CURSOR
for SELECT top 4 period from Course instance
where year = @year

open myCursor1

fetch next from myCursor1 into @variable
--print @variable

while @@fetch_status = 0
    Begin

    UPDATE @Table2
    SET InstanceCourse1 = @variable
    where current of myCursor1

    fetch next from myCursor1 into @variable
    print @variable

    End

Close myCursor1
deallocate myCursor1

insert into @table1
select 'Firstname', 'Lastname'

insert into @table1
select Firstname, Lastname from staff order by Lastname

END

select * from @Table1 -- for testing purposes
select * from @Table2 -- for testing purposes
--Then i want to combine these tables into the output at the top

这是我已经走了多远,我不知道如何将课程纳入专栏,然后获得每个工作人员的小时数。

如果有人能帮助指导我朝着正确的方向前进,我将非常感激。我对光标的想法是从那一年的前4个课程期间获得最高(0-4)值,然后将它们添加到@table2

3 个答案:

答案 0 :(得分:2)

试试这个

DECLARE @CourseNameString varchar(max),
    @query  AS NVARCHAR(MAX);

    SET @CourseNameString=''
select @CourseNameString = STUFF((SELECT distinct ',' + QUOTENAME(Course) 
                   FROM Attended where [Year]= 2013
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = '
select Name,LastName,'+@CourseNameString+' from Staff as e inner join (

 SELECT * FROM
(SELECT [Hours],a.SSN,a.Course as c FROM Attended as a inner JOIN Staff as s
ON s.SSN = s.SSN) p
PIVOT(max([Hours])FOR c IN ('+@CourseNameString+')) pvt)p
 ON e.SSN = p.SSN'

  execute(@query)

答案 1 :(得分:2)

确定。这不漂亮。这是一个非常丑陋的动态sql,但在我的测试中它似乎正在工作。我创建了一个额外的子查询,将课程值作为第一行,然后将Union与结果的其余部分一起使用。前四个课程通过使用ROW_Number()和按年份和期间的顺序收集。我必须创建我正在创建的课程字符串的不同版本,以便将它们用于列名和我的支点。试试看。希望它也可以处理您的数据。

DECLARE @Year INT
SET @Year = 2014
DECLARE @Query NVARCHAR(2000)

DECLARE @CoursesColumns NVARCHAR(2000) 
SET @CoursesColumns = (SELECT '''' + Course + ''' as c' + CAST(ROW_NUMBER() OVER(ORDER BY Year,     Period) AS nvarchar(50)) + ',' AS 'data()'
FROM AttendedBy where [Year] = @Year
for xml path(''))
SET @CoursesColumns = LEFT(@CoursesColumns, LEN(@CoursesColumns) -1)
SET @CoursesColumns = 
CASE 
    WHEN CHARINDEX('c1', @CoursesColumns) = 0 THEN @CoursesColumns + 'NULL as c1, NULL as c2, NULL as c3, NULL as c4'
    WHEN CHARINDEX('c2', @CoursesColumns) = 0 THEN @CoursesColumns + ',NULL as c2, NULL as c3, NULL as c4'
    WHEN CHARINDEX('c3', @CoursesColumns) = 0 THEN @CoursesColumns + ', NULL as c3, NULL as c4'
    WHEN CHARINDEX('c4', @CoursesColumns) = 0 THEN @CoursesColumns + ', NULL as c4'
    ELSE @CoursesColumns
END

DECLARE @Courses NVARCHAR(2000) 
SET @Courses = (SELECT Course + ' as c' + CAST(ROW_NUMBER() OVER(ORDER BY Year, Period) AS     nvarchar(50)) + ',' AS 'data()'
FROM AttendedBy where [Year] = @Year
for xml path(''))
SET @Courses = LEFT(@Courses, LEN(@Courses) -1)
SET @Courses = 
CASE 
    WHEN CHARINDEX('c1', @Courses) = 0 THEN @Courses + 'NULL as c1, NULL as c2, NULL as c3, NULL as c4'
    WHEN CHARINDEX('c2', @Courses) = 0 THEN @Courses + ',NULL as c2, NULL as c3, NULL as c4'
    WHEN CHARINDEX('c3', @Courses) = 0 THEN @Courses + ', NULL as c3, NULL as c4'
    WHEN CHARINDEX('c4', @Courses) = 0 THEN @Courses + ', NULL as c4'
    ELSE @Courses
END

DECLARE @CoursePivot NVARCHAR(2000) 
SET @CoursePivot = (SELECT  Course + ',' AS 'data()'
FROM AttendedBy where [Year] = @Year
for xml path(''))
SET @CoursePivot = LEFT(@CoursePivot, LEN(@CoursePivot) -1)

SET @Query = 'SELECT Name, LastName, c1, c2, c3, c4
FROM (
SELECT ''Name'' as name, ''LastName'' as lastname, ' +  @CoursesColumns +
' UNION

SELECT Name, LastName,' + @Courses +
' FROM(

SELECT 
    s.Name
    ,s.LastName
    ,ci.Course
    ,ci.Year
    ,ci.Period
    ,CAST(ab.Hours AS NVARCHAR(100)) AS Hours
FROM Staff s
LEFT JOIN AttendedBy ab
ON
s.SSN = ab.SSN
LEFT JOIN CourseInstance ci
ON
ab.Course = ci.Course
WHERE ci.Year=' + CAST(@Year AS nvarchar(4)) +
' ) q
PIVOT(
    MAX(Hours)
FOR 
    Course
IN (' + @CoursePivot + ')
)q2
)q3'


SELECT @Query
execute(@Query)

编辑:添加了一些where子句,因此只显示给定年份的课程。添加了我的结果截图。 enter image description here

答案 2 :(得分:0)

使用像这样的子查询:

SELECT Firstname, Lastname, (select instanceCourse1 from table2) as InstanceCourse1 from Table1