Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
SubCreator
Starting Member
8 Posts |
Posted - 2004-06-28 : 04:41:06
|
| HiI have one table containing studentID, ExamCode and Grade.I would of course view this table as a pivot.But I just get error messages. How would you (people who know this by heart) write that procedure call?-- SubCreator |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2004-06-28 : 13:59:38
|
| What are your error messages? Please post your code.Tara |
 |
|
|
fjorner
Starting Member
5 Posts |
|
|
kselvia
Aged Yak Warrior
526 Posts |
Posted - 2004-06-29 : 00:33:50
|
| Read the article above. Essentialy this:DECLARE @sql varchar(8000)SELECT @sql = COALESCE(@sql + ',', 'select studentID, ') + replace('[~] = sum(case when ExamCode=~ then Grade else 0 end)','~',ExamCode) FROM (select distinct ExamCode from mytable) xSET @sql = @sql + ' from mytable group by studentID'EXEC (@sql) |
 |
|
|
SubCreator
Starting Member
8 Posts |
Posted - 2004-06-29 : 03:31:11
|
| Of course I've read the article, and the discussion related to it. I'm basically stupid :):)My table has these fields: School Study StudentID ExamCode GradeI would (optimally) like to have the following output:School | Study | Studentid | Examcode1 | Examcode n...-----------------------------------------------------------MySchool | MyStudy | 1234 | B+ | C- ...etc...Anyone?I run an SQL Server 2000, and the table is pretty big.Which of the crosstab scripts should I use, in your opinion? (I registrered that a lot of improvement has been made to the original script.-- SubCreator |
 |
|
|
kselvia
Aged Yak Warrior
526 Posts |
Posted - 2004-06-29 : 03:53:53
|
The code I posted should do that if you add School and Study like so:DECLARE @sql varchar(8000)SELECT @sql = COALESCE(@sql + ',', 'select School, Study, Studentid, ') + replace('[~] = sum(case when ExamCode=~ then Grade else 0 end)','~',ExamCode) FROM (select distinct ExamCode from mytable) xSET @sql = @sql + ' from mytable group by School, Study, Studentid'EXEC (@sql)I have also used this version and it worked well for me. [url]http://www.experts-exchange.com/Databases/Microsoft_SQL_Server/Q_20333808.html[/url]Run it with: exec sp_crosstab @tablename = N'MyTable', @crosscolumn = N'StudentID', @crossrow = N'ExamCode', @crossvalue = N'Grade', @where = N'WHERE MySchool=''someschool''' But it will not include School and Study in the output. Maybe one of the other versions will, but the dynamic SQL I showed above should also work.It has a limit on the number of columns and size of the dynamic SQL you can build. This version is supposed to support 700+ columns, but I have not used it: [url]http://www.developersdex.com/gurus/code/826.asp[/url]CREATE procedure sp_CrossTab @tablename varchar(255), -- Table/View on which to perform the cross tab query. @crosscolumn varchar(255), -- Attribute to be used as columns in the cross tab. @crossrow varchar(255), -- Attribute to be used as rows in the cross tab. @crossvalue varchar(255) -- Attribute to be used as value in the cross tab.As-- Work variablesdeclare @sql varchar(8000), -- Hold the dynamically created sql statement @colname varchar(255), -- The current column when building sql statement @i smallint, -- know when we reached the last column (@i = @cols) @cols smallint, -- Number of columns @longest_col smallint, -- the len() of the widest column @CrLf char(2)-- Constantsdeclare @max_cols_in_table smallint, @max_col_name_len smallint, @max_statement_len smallint,-- @sql7 bit, -- 1 when version 7, 0 otherwise. @err_severity intset nocount onset @max_cols_in_table = 255set @max_statement_len = 8000set @max_col_name_len = 128set @err_severity = 11set @CrLf = char(13) + char(10)-- Check inputsif @tablename is null or @crosscolumn is null or @crossrow is null or @crossvalue is null begin raiserror ('Missing parameter(s)!',@err_severity,1) return 0end-- Check for existence of the table.if (not exists(select * from sysobjects where name like @tablename))begin raiserror ('Table/View for crosstab not found!',@err_severity,1) return 0end-- Don't check for columns because we may actually get an expression as the column name-- prepare for future feature of checking database version to validate -- inputs. Default to version 7--set @sql7 = 1--if (patindex('%SQL Server 7.%',@@version) = 0) begin -- set @sql7 = 0--end-- Extract all values from the rows of the attribute -- we want to use to create the cross column. This table-- will contain one row for each column in the crosstab.create table #crosscol (crosscolumn varchar(255))set @sql = ' insert #crosscol Select Distinct ' + @crosscolumn + ' From ' + @tablename --+ --' Group By ' + @crosscolumn--print @sqlexec (@sql)set @cols = @@rowcountif @cols > @max_cols_in_table begin raiserror ('Exceeded maximum number of columns in Cross-tab',@err_severity,1) return 0endelse begin if @cols = 0 begin raiserror ('Could not find values to use for columns in Cross-tab',@err_severity,1) return 0 end else begin -- Check if any of the data is too long to make it a name of a column select @longest_col = max(len(convert(varchar(129),crosscolumn))) from #crosscol if @longest_col > @max_col_name_len begin raiserror ('Value for column name exceeds legal length of column names',@err_severity,1) return 0 end else begin -- All Validations OK, start building the dynamic sql statement set @sql = '' -- Use tmp table rows to create the sql statement for the crosstab. -- each row in the table will be a column in the cross-tab set @sql = 'select isnull(convert(varchar(255), ' + @crossrow + '),''Undefined'') As ' + @crossrow + ', ' + @CrLf + space(4) --set @sql = 'select ' + @crossrow + ', ' + char(13) declare cross_sql cursor for select crosscolumn from #crosscol order by crosscolumn --print 'Sql cross statment: ' + @sql open cross_sql fetch next from cross_sql into @colname -- Use "@i" to check for the last column. We need to input commas -- between columns, but not after the last column set @i = 0 while @@FETCH_STATUS = 0 begin set @i = @i + 1 set @colname = isnull(@colname,'Undefined') set @crossvalue = isnull(@crossvalue, 0) Set @sql = @sql + '''' + convert(varchar(128), @colname) + ''' = sum(case convert(varchar(128), ' + @crosscolumn + ')' + char(13) + char(10) + space(8) + ' when ''' + @colname + ''' then ' + @crossvalue + ' else 0 end) ' if @i < @cols set @sql = @sql + ', ' + @CrLf + space(4) else set @sql = @sql + @CrLf fetch next from cross_sql into @colname end close cross_sql deallocate cross_sql set @sql = @sql + ' from ' + @tablename + ' Group By ' + @crossrow if len(@sql) >= @max_statement_len begin raiserror ('Crosstab sql statement cannot exceed 7999 characters',@err_severity,1) return 0 end exec (@sql) Select 'Sql' = @sql set nocount off return 1 end endendGO |
 |
|
|
SubCreator
Starting Member
8 Posts |
Posted - 2004-06-29 : 05:05:35
|
| Thanks. I didn't quite understand that you had made another script doing the same thing, and actually make it so small.I tried you script, but got these message back.(I'm not into SQL Scripting, just to say that!)The examcode is alphanumeric, and so is the grades, actually. Basicly, all fields are alphanumeric.Server: Msg 207, Level 16, State 3, Line 1Invalid column name 'MSAFP'.Server: Msg 207, Level 16, State 1, Line 1Invalid column name 'MSEPPF'.Server: Msg 207, Level 16, State 1, Line 1Invalid column name 'MSTER'.Stored Procedure: studentservice.dbo.sp_Karakterer Return Code = 0-- SubCreator |
 |
|
|
kselvia
Aged Yak Warrior
526 Posts |
Posted - 2004-06-29 : 19:41:56
|
| Please post the query you tried to run. |
 |
|
|
SubCreator
Starting Member
8 Posts |
Posted - 2004-06-30 : 03:24:31
|
| I made it!DECLARE @sql varchar(8000)SELECT @sql = COALESCE(@sql + ',', 'select School, Study, Studentid, ') + replace('[~] = Min(case when ExamCode=''~'' then Grade else NULL end)','~',ExamCode) FROM (select distinct ExamCode from KAR) xSET @sql = @sql + ' from KAR group by School, Study, Studentid'exec (@sql)GOI had to change the grade to a vchar, and the else-value to NULL, and put the fields ExamCode in the group clause.-- SubCreator |
 |
|
|
kselvia
Aged Yak Warrior
526 Posts |
Posted - 2004-06-30 : 12:08:17
|
| Glad to help. |
 |
|
|
|
|
|
|
|