【问题标题】:How Can I Create Dynamic Rows to Columns in sql server 2005?如何在 sql server 2005 中为列创建动态行?
【发布时间】:2012-05-06 13:56:30
【问题描述】:

我正在使用带有 c# 的 SQL Server 2005 和 asp.net 2008...我有 2 个表 Result 和 Stud_Info.......

1] Stud_Info

CREATE TABLE Stud_Info
(Enroll_Number varchar(20) NOT NULL,  
Salutation varchar(10) NULL,  
First_Name varchar(20) NULL,  
Middle_Name varchar(20) NULL,  
Last_Name varchar(20) NULL,  
Course_Id varchar(20) NULL,  
Batch varchar(20) NULL)

INSERT into Stud_Info values(11161,'Mr.','Mack','B','Botha','MECH','Batch1');    
INSERT into Stud_Info values(11162,'Mr.','John','A','Los','CIVIL','Batch2');    
INSERT into Stud_Info values(11163,'Ms.','Merry','F','Dsuza','ELCT','Batch1');    
INSERT into Stud_Info values(11164,'Mr.','Pow','B','Janero','MECH','Batch2');    
INSERT into Stud_Info values(11165,'Mr.','Martin','J','Smith','MECH','Batch1');    

SELECT * from Stud_Info  

第二张桌子是这样的……

2] Exam_Result

CREATE TABLE Exam_Result
(Result_Id numeric(18, 0) IDENTITY(1,1) NOT NULL,  
Enroll_Number varchar(50) NULL,  
Student_Name varchar(100) NULL,  
Course_Id varchar(50) NULL,  
Semester varchar(50) NULL,  
Subject_Id varchar(50) NULL,  
Subject_Name varchar(50) NULL,  
MarksObtained numeric(18, 0) NULL,  
Exam_Type varchar(50) NULL)

INSERT into Exam_Result values(11161,'Mack B Botha','MECH',1,'MT','Maths',25,'Internal1');  
INSERT into Exam_Result values(11161,'Mack B Botha','MECH',1,'EN','English',22,'Internal1');  
INSERT into Exam_Result values(11161,'Mack B Botha','MECH',1,'SC','Science',20,'Internal1');  
INSERT into Exam_Result values(11166,'Barden V John','CIVIL',1,'SS','Social',21,'Internal2');  
INSERT into Exam_Result values(11161,'Mack B Botha','MECH',2,'SM','Simple Maths',24,'Internal2');  
INSERT into Exam_Result values(11161,'Mack B Botha','MECH',2,'SM','Simple Maths',69,'Final');  

SELECT * from Exam_Result

&

Exam_Result 是这样的......

Result_Id  Enroll_No  Student_Name  Course_ID  Semester  Subject_Id  Subject_Name   Marks    Type    

1          11161      Mack B Botha   MECH       1         MT          Maths           25     Internal1

2          11161      Mack B Botha   MECH       1         EN          English         22     Internal1

3          11161      Mack B Botha   MECH       1         SC          Science         20     Internal1

4          11166      Barden V John  CIVIL      1         SS          Social          21     Internal2

5          11161      Mack B Botha   MECH       2         SM          Simple Maths    24     Internal2

6          11161      Mack B Botha   MECH       2         SM          Simple Maths    69     Final

我正在使用此 PIVOT 查询将主题的行动态转换为列......并且效果很好。

declare @subjname varchar(100)  
declare @subjects varchar(7000)  
declare @subjectsselection varchar(7000)  

set @subjects = ''  
set @subjectsselection = ''  

DECLARE subject_cursor CURSOR  
FOR SELECT distinct Subject_Id FROM Result  
OPEN subject_cursor  
FETCH NEXT FROM subject_cursor  
INTO @subjname  
WHILE @@FETCH_STATUS = 0  
BEGIN  
set @subjects = @subjects + '[' + @subjname + ']'  
set @subjectsselection = @subjectsselection + 'Isnull([' + @subjname + '],0) As ' + @subjname  

set @subjects = @subjects + ','  
set @subjectsselection = @subjectsselection + ','  

FETCH NEXT FROM subject_cursor  
INTO @subjname  
End  
CLOSE subject_cursor;  
DEALLOCATE subject_cursor;  

select @subjects = LEFT(@subjects, LEN(@subjects) - 1)  
select @subjectsselection = LEFT(@subjectsselection, LEN(@subjectsselection) - 1)  

print @subjects  
print @subjectsselection  

declare @query nvarchar(4000)  

set @query = 'select Enroll_Number, ' + @subjectsselection + ' From '  
set @query = @query + '(select Enroll_Number, Subject_Id, MarksObtained from Result ) ps '  
set @query = @query + 'pivot(sum(MarksObtained) for Subject_Id in (' + @subjects + ')) as pvt'  

exec sp_executesql @query  

目前我正在接受 o/p 之类的......

Enroll_Number    MT    EN    SC    SS    SM    

11161            25    22    20    0     83
11166            0     0     0     21    0

这里我得到的是子 SM 的总和,即 24 + 69 = 83,但我希望每个学生的总数和平均值

现在的问题是我想通过根据用户的选择来显示结果.... 例如,如果用户只想查看 Course_Id = MECH 和 Semester = 1 ....o/p 应该是....

Enroll_No    Student_Name    Course_ID    Semester    Maths    English    Science     Type         Grand_Total    Avg

11161        Mack B Botha     MECH         1          25        22        20        internal1       67          66.22

每门课程和学期没有固定的科目数..可能会发生变化..需要按 Course_Id 和 Semester 分组给我指导和查询,以便我实施你的回答......我希望这些信息足以解释我的东西......请帮助我先生......谢谢

【问题讨论】:

  • 如果您要发布表架构和数据输出,花点时间正确格式化。在帖子编辑器中缩进 4 个空格以获得类似上面的代码输出,并将其隔开,以便所有列都正确排列。我这样做的部分原因是为了让你开始。
  • 您可以发布每个表的示例数据吗?看起来您发布的内容是当前查询的结果。查看每个表的细分以及您当前的查询会很有帮助。
  • 是的,先生,当然……谢谢指导……

标签: c# asp.net sql sql-server-2005 visual-studio-2008


【解决方案1】:

将代码移到存储过程中

    /*
    GetExamResults 'MECH', '2'
*/
Create Proc GetExamResults (@Course_Id varchar(100), @Semester varchar(10))
as
begin
    declare @subjname varchar(100)  
    declare @subjects varchar(7000)  
    declare @subjectsselection varchar(7000)  
    declare @SumSelection varchar(7000)  
    declare @NoOfSubjects int
    set @NoOfSubjects = 0

    set @subjects = ''  
    set @subjectsselection = '' 
    set @SumSelection = ''

    DECLARE subject_cursor CURSOR  
    FOR SELECT distinct Subject_Name FROM Exam_Result where course_id = @Course_Id And Semester = @Semester 

    OPEN subject_cursor  

    FETCH NEXT FROM subject_cursor  
    INTO @subjname  

    WHILE @@FETCH_STATUS = 0  
    BEGIN  
        set @subjects = @subjects + '[' + @subjname + '],'  
        set @subjectsselection = @subjectsselection + 'Sum(Isnull([' + @subjname + '],0)) As [' + @subjname + '],' 
        set @SumSelection = @SumSelection + 'Sum(Isnull([' + @subjname + '],0))+' 

        set @NoOfSubjects = @NoOfSubjects + 1

        FETCH NEXT FROM subject_cursor  
        INTO @subjname  
    End  
    CLOSE subject_cursor;  
    DEALLOCATE subject_cursor;  

    select @subjects = LEFT(@subjects, LEN(@subjects) - 1)  
    select @subjectsselection = LEFT(@subjectsselection, LEN(@subjectsselection) - 1)  
    select @SumSelection = LEFT(@SumSelection, LEN(@SumSelection) - 1)  

    print @subjects  
    print @subjectsselection  
    print @SumSelection

    declare @query nvarchar(4000)  

    set @query = 'select S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, ' + @subjectsselection + ',' 
    set @query = @query + 'Exam_Type,' + @SumSelection + ' As Grand_Total, '
    set @query = @query + '(' + @SumSelection + ')' + '/' + convert(varchar(10),@NoOfSubjects) + ' As Avg'
    set @query = @query + ' From '  
    set @query = @query + '(select Enroll_Number, Student_Name, Course_Id, Semester, Subject_Name, MarksObtained, Exam_Type from Exam_Result ) ps '  
    set @query = @query + ' pivot(sum(MarksObtained) for Subject_Name in (' + @subjects + ')) as pvt'  
    set @query = @query + ' inner join Stud_Info S on S.Enroll_Number = pvt.Enroll_Number '
    set @query = @query + ' where pvt.Course_Id = ''' + @Course_Id + ''' and pvt.Semester = ''' + @Semester + ''''
    set @query = @query + ' group by S.Enroll_Number, pvt.Student_Name, pvt.Course_Id, pvt.Semester, Exam_Type'
    print @query
    exec sp_executesql @query  
end

【讨论】:

  • 它给出了这样的错误... Msg 139,Level 15,State 1,Procedure GetExamResults,Line 0 无法为局部变量分配默认值。消息 137,级别 15,状态 2,过程 GetExamResults,第 28 行 必须声明标量变量“@NoOfSubjects”。消息 137,级别 15,状态 2,过程 GetExamResults,第 48 行 必须声明标量变量“@NoOfSubjects”。 ** 你能解释一下为什么它会出现这样的错误 ** thnks for guidence
  • Shamjith Haridasan 先生,我收到此消息:命令已成功完成。我通过简单地编辑 declare #NoOfSubjects int 并在此处设置 set #NoOfSubjects = 0 解决了这个问题... 对吗?? 如果是那么我怎样才能执行这个过程并得到一些结果....或者我必须改变任何其他方面??请阻止我先生....谢谢
  • 先生,谢谢它真的对我有用....但只有**主要问题**是 它检索了 Exam_Result 表中的所有科目...我到底是什么想要的是,例如 我只需要指定 *COURSE_ID(MECH) 和 SEMESTER(1) 科目(数学、英语、科学) 中的科目,然后我想该科目的总和和该科目的平均值*......在这方面需要帮助......请帮助我......我们离成功更近了。 !!在此先感谢....
【解决方案2】:

您可以查看 SQL Server 中的 PIVOT 功能:http://msdn.microsoft.com/en-us/library/ms177410.aspx

但是,该语句可能需要使用存储过程动态构建。

【讨论】:

  • 亲爱的 sascha,你能不能给我最合适的例子或链接,因为我要求学生成绩...我没有得到动态的科目...
【解决方案3】:

我们可以使用 PIVOT 和动态 sql 语句来实现这一点。例如我们有一个名为 sales 的表,如下所示。

create table Sales (SalesPerson varchar(100), Product varchar(50), SamesAmount numeric (18,2))

insert into Sales (SalesPerson, Product, SamesAmount)
select 'Bob',   'Pickles', 100.00
union all
select 'Sue',   'Oranges', 50.00
union all
select 'Bob',   'Pickles', 25.00
union all
select 'Bob',   'Oranges', 300.00
union all
select 'Sue',   'Oranges', 500.00

PIVOT 查询是

select salesperson, Isnull([Oranges],0) As Oranges, Isnull([Pickles],0) As Pickles
From
(select SalesPerson, Product, SamesAmount from Sales ) ps
pivot(sum(SamesAmount) for product in ([Oranges],[Pickles])) as pvt

由于主题的数量是可以变化的,所以我们要构建动态的sql查询。

declare @productname varchar(100)
declare @products varchar(7000)
declare @productsselection varchar(7000)

set @products = ''
set @productsselection = ''

DECLARE product_cursor CURSOR
    FOR SELECT distinct Product FROM Sales
OPEN product_cursor
FETCH NEXT FROM product_cursor
INTO @productname
WHILE @@FETCH_STATUS = 0
BEGIN
    set @products = @products + '[' + @productname + ']'
    set @productsselection = @productsselection + 'Isnull([' + @productname + '],0) As ' + @productname

    set @products = @products + ','
    set @productsselection = @productsselection + ','

    FETCH NEXT FROM product_cursor
    INTO @productname
End
CLOSE product_cursor;
DEALLOCATE product_cursor;

select @products = LEFT(@products, LEN(@products) - 1)
select @productsselection = LEFT(@productsselection, LEN(@productsselection) - 1)

print @products
print @productsselection

declare @query nvarchar(4000)

set @query = 'select salesperson, ' + @productsselection + ' From '
set @query = @query + '(select SalesPerson, Product, SamesAmount from Sales ) ps '
set @query = @query + 'pivot(sum(SamesAmount) for product in (' + @products + ')) as pvt'

exec sp_executesql @query

【讨论】:

  • 先生,您能帮帮我吗,我仍然想要一些更改....我已将我的查询更新为上述问题....找出问题的解决方案....谢谢回复跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
相关资源
最近更新 更多