Pivoting SQL Server 2005 for unknown number of rows - sql

My table is a dynamic one. E.g.:
id SUBJECT
1 his
2 math
3 sci
4 opt
5 ENG
6 SOC
The number of rows is not limited. There could be a hundred. I want output like this:
ID 1 2 3 4 5 6
HIS MATH SCI OPT ENG SOC
I could use a pivot query, but I would have to know the number of columns. How can I do this without knowing the number of columns in advance?

i got an answer but it's very tricky
create a table for all your records
count the records
create a table with that much number of columns
create a comma separated variable for the table which has records
then split the comma separated variables into multiple columns
here is the code
DECLARE #HEADDESC NVARCHAR(150)
DROP TABLE #HEADS
CREATE TABLE #HEADS
(
ID INT IDENTITY
,HEADS NVARCHAR(150)
,NU INT
)
DECLARE #NO INT;
SET #NO = 0
DECLARE C1 CURSOR FOR (
SELECT HEADDESC
FROM GMC.FEEHEAD_MASTER
WHERE CODE = 'GF' AND HEADDESC <> '')
OPEN C1
FETCH NEXT FROM C1 INTO #HEADDESC
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #HEADDESC
SET #NO = #NO+1
INSERT INTO #HEADS(HEADS,NU)
VALUES(#HEADDESC,#NO)
FETCH NEXT FROM C1 INTO #HEADDESC
END
--SELECT * FROM #HEADS
CLOSE C1
DEALLOCATE C1
DECLARE #COLNO INT
SET #COLNO = (SELECT COUNT(*) FROM #HEADS)
DECLARE #COLUMNS VARCHAR(8000)
SELECT #COLUMNS = COALESCE(#COLUMNS +','+ CAST(HEADS AS VARCHAR) ,
CAST(HEADS AS VARCHAR))
FROM #HEADS
--GROUP BY HEADS
DECLARE #value NVARCHAR(100)
SET #value = ',1,STUDENTIDNO,STUDENTNAME,'
SET #COLUMNS = #VALUE+#COLUMNS
SET #COLNO = #COLNO+4
--SELECT #COLUMNS
DROP TABLE #HEADSCOMMA
CREATE TABLE #HEADSCOMMA(HEADS NVARCHAR(3000))
INSERT INTO #HEADSCOMMA VALUES (#COLUMNS)
DROP TABLE #TEMP
CREATE TABLE #TEMP(COL1 NVARCHAR(1000))
DECLARE #SQL NVARCHAR(MAX)
DECLARE #COL NVARCHAR(1000)
DECLARE #COL1 INT
DECLARE #COLNAME NVARCHAR(1000)
SET #COL1 = 2
SET #COL = 'COL'
PRINT #COL1
--SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(10))
WHILE #COL1 < =#COLNO
BEGIN
SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(100))
PRINT #COLNAME
SET #SQL = 'ALTER TABLE #TEMP ADD '+#COLNAME+' NVARCHAR(100)'
EXEC(#SQL)
SET #COL1= #COL1+1
END
--SELECT * FROM #HEADSCOMMA -- COMMA SEPERATED VALUES
DECLARE #S VARCHAR(8000), #DATA VARCHAR(8000)
--DROP TABLE #NORMALISEDTABLE
--CREATE TABLE #NORMALISEDTABLE (HEADS NVARCHAR(200))
SELECT #S=''
WHILE EXISTS (SELECT * FROM #HEADSCOMMA WHERE HEADS>#S)
BEGIN
SELECT #S=HEADS FROM #HEADSCOMMA WHERE HEADS>#S
PRINT #S
SELECT #DATA=''''+REPLACE(#S,',',''',''')+''''
PRINT #DATA
INSERT INTO #TEMP
EXEC('SELECT '+#DATA)
END
SELECT * FROM #temp
will give the records

Dynamic SQL is an option.

Related

How to declare temponary/variable table with a dynamic number of column

I have table like this:
Table Name|Number of columns
How to dynamically create temporary tables inside stored procedure with names from first table, and variable columns named e.g. col1, col2, etc..
I also need to insert values to them and make another logic on them.
Example:
Table1|3
Table1(col1 nvarchar(max), col2 nvarchar(max), col3 nvarchar(max))
You will need to use dynamic sql like below:
declare #counter int = 1
declare #numberOfCols int = 3 -- OR you can use ->(select numberofcolumns from firsttable)
declare #dynamic nvarchar(max) = ''
declare #sql nvarchar(max) = 'CREATE TABLE #TEMP (';
while #counter <= #numberofCols
begin
set #dynamic = #dynamic + 'col'+cast(#counter as nvarchar(5))+' nvarchar(max) ';
if(#counter <> #numberOfCols)
begin
set #dynamic = #dynamic + ', ';
end
set #counter = #counter + 1
end
set #sql = #sql + #dynamic + ') select * from #temp'
select #sql
EXECUTE sp_executesql #sql
I have created a stored procedure regarding your question. I wish it can help you.
ALTER PROCEDURE P_ProcedureName
#NumberOfColumns INT=2 --expected 1 or more column
AS
DECLARE #SQLString VARCHAR(MAX)=''
DECLARE #Seq INT=2
IF #NumberOfColumns=0
BEGIN
SELECT 'Please add valid number of column'
RETURN
END
CREATE TABLE #Table
(
Id INT NOT NULL IDENTITY(1,1)
,Column1 VARCHAR(MAX)
)
WHILE #Seq<=#NumberOfColumns
BEGIN
SET #SQLString=#SQLString+'ALTER TABLE #Table ADD Column'+CAST(#Seq AS VARCHAR)+' VARCHAR(MAX)'+char(13)
PRINT(#SQLString)
SET #Seq +=1
END
EXEC(#SQLString)
SELECT * FROM #Table
GO
P_ProcedureName 5

Values not passed to dynamic query in sql server

Is it possible to print the Dynamic select statement after passing the parameters values.When i print the SELECT #SQL.It is giving only select statement without parameter values.In my below procedure the dynamic select statement not giving correct output after passing the parameters.But when i directly passing the the parameter values into the select statement it is giving correct output.In my below procedure splitting function is working fine.Else part in
if statement is not working properly.
CREATE TYPE TableVariable AS TABLE
(
id int identity(1,1),
field_ids INT,
value VARCHAR(MAX)
)
Alter PROCEDURE Testing
(
#TableVar TableVariable READONLY,
#Catalog_id INT
)
AS
Declare #maxPK INT
Declare #pk INT
Declare #fid INT
Declare #is_List SMALLINT
Declare #val VARCHAR(MAX)
Declare #field_Type VARCHAR(50)
Declare #Where VARCHAR(MAX)
Declare #SQL NVARCHAR(MAX);
Set #pk = 1
BEGIN
BEGIN TRY
SET NOCOUNT ON;
Select #maxPK = count(*) From #TableVar
SELECT #Catalog_id
Set #SQL = 'SELECT DISTINCT v1.entity_id from values v1 inner join listings l ON v1.entity_id = l.entity_id WHERE l.c_id=#Catalog_id'
While #pk <= #maxPK
BEGIN
SELECT #fid= field_ids FROM #TableVar where id=#pk;
SELECT #val= value FROM #TableVar where id=#pk;
SELECT #field_Type=type,#is_List=is_list FROM FIELD WHERE ID=#fid
IF (#is_List = 0)
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value IN(SELECT val FROM spliting(#val,'',''))))'
SELECT #fid
END
else IF (#is_List = 1 OR #field_Type = 'xy')
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value in(#val)))'
SELECT #fid
END
Select #pk = #pk + 1
END
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
SELECT #SQL
END TRY
BEGIN CATCH
END CATCH
END
DECLARE #DepartmentTVP AS TableVariable;
insert into #DepartmentTVP values(1780,'Smooth As Silk Deep Moisture Shampoo,Smooth As Silk Deeper Moisture Conditioner')
--insert into #DepartmentTVP values(1780,'Smooth As Silk Deeper Moisture Conditioner')
insert into #DepartmentTVP values(1782,'037-05-1129')
insert into #DepartmentTVP values(2320,'["fairtrade","usda_organic","non_gmo_verified"]')
SELECT * FROM #DepartmentTVP
EXEC Testing #DepartmentTVP,583
Yes right before the statment:
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
type:
print #SQL

SQL Server INSERT in Loop

I have this SQL Script:
DECLARE #Loop INT
SET #Loop = 1
DECLARE #Result table([1] int, [2] int,[3] int,[4] int,[5]);
WHILE (#Loop <=5)
BEGIN
INSERT INTO #Result(#Loop)
SELECT Id FROM Students WHERE Id=#Loop
SET #Loop= #Loop+ 1
END
I got an error in this line:
INSERT INTO #Result(#Loop)
Is it possible to use this way to insert data into column names using loop ? I mean dynamicaly
Thanks
This is as close as I can get to what you have.
I'm using dynamic sql to build the insert sql.
I'm using a temporary table #Result instead of a variable #Result because the scope of the #Result variable would mean that this technique would not work.
DECLARE #Loop INT;
SET #Loop = 1;
CREATE TABLE #Result([1] int, [2] int, [3] int, [4] int, [5] int);
DECLARE #Sql AS NVARCHAR(MAX);
DECLARE #LoopNVARCHAR AS NVARCHAR(10);
WHILE (#Loop <= 5)
BEGIN
SET #LoopNVARCHAR = CAST(#Loop AS NVARCHAR(10));
SET #Sql = N'INSERT INTO #Result([' + #LoopNVARCHAR + ']) SELECT Id FROM Students WHERE Id = ' + #LoopNVARCHAR;
exec (#Sql)
SET #Loop = #Loop + 1
END
SELECT * FROM #Result
DROP TABLE #Result

How to retrieve N random records from stored procedure?

How can I retrieve N random records from a set of X records we have in total. For example, if we have a table with 2000 links to different pages on our website how do we retrieve 10 random records?
SELECT TOP 10 *
FROM tableName
ORDER BY NEWID()
NEWID
Try using dynamics SQL like this. Note that this needs more work since some edge cases are not covered such as COUNT() returning 0 or cases where record count is greater than COUNT() and such.
CREATE PROCEDURE dbo.RandomNRecords
(
#recordCount int
)
as
begin
declare #counter int
declare #sqlQuery nvarchar(2000)
SET #sqlQuery = '
CREATE TABLE #TempTable
(
f1 varchar(50),
f2 varchar(50),
f3 int,
id int identity(1,1)
)
INSERT INTO #TempTable
SELECT f1, f2, f3 FROM Table1
SELECT *
FROM #TempTable
WHERE id in ('
SELECT #recordCount = COUNT(*) From Table1
SET #counter = 0
WHILE #counter < #recordCount
BEGIN
SET #counter = #counter + 1
SET #sqlQuery = #sqlQuery + CONVERT(varchar,Round((#recordCount * Rand()), 0)) + ','
END;
SET #sqlQuery = SUBSTRING(#sqlQuery, 1, LEN(sqlQuery) - 1) --remove last comma
SET #sqlQuery = #sqlQuery + ')'
EXEC sp_executesql #sqlQuery
END
declare #numberOfRecordsToGet int = 5
select top (#numberOfRecordsToGet) * from name_of_your_tbl order by newid()
use this in store procedure
declare #N varchar(10)
set #N='10'
exec(' SELECT TOP '+#N+' * FROM tableName ORDER BY NEWID()')

How can show one Row in rows in which each row contain column name and the other contain the value?

I have a table that contain about 60 columns and if i write a select query in query analyser to get a row it show it and i must scroll to show data ..
How can i get one row in which it shows as 60 row, each row contain 2 columns one for column name and other for value
For example Select * from table where id = 1 in default it shown as
ID Col1 Col2 Col3 Col4 Col5 ...... Col60
1 v1 v2 v3 v4 v5 ...... v60
I want it to be shown as
ID 1
Col1 v1
Col2 v2
Col3 v3
...
Col60 v60
The below Stored Procedure do What you need
CREATE PROCEDURE [dbo].[Rotat]
-- Add the parameters for the stored procedure here
#Where nvarchar(max),
#tableName nvarchar(max)
AS
BEGIN
Declare #SqlQuery nvarchar(max),#ColumnName nvarchar(255)
DECLARE #TempTable TABLE
(
ID int IDENTITY(1,1) ,
ColumnName nvarchar(255),
ColumnValue ntext
)
INSERT INTO #TempTable (ColumnName)
SELECT column_name
FROM information_schema.columns
WHERE table_name = #tableName
Declare #index int
Set #index = 1;
Declare #Count int
Select #Count = Count(ID) from #TempTable
declare #columnValue nvarchar(255)
declare #paraDef nvarchar(max)
declare #string nvarchar(max)
WHILE #index <= #Count
BEGIN
Select #ColumnName = ColumnName from #TempTable where id = #index
set #string ='select #ret= cast('+ #ColumnName + ' AS nvarchar(255) )
from '+#tableName+' WHERE ' + #Where
set #paraDef=N'#ret nvarchar(255) output'
EXECUTE sp_executesql #string, #paraDef,#ret=#ColumnValue output
UPDATE #TempTable
SET ColumnValue = #columnValue
WHERE ID =#index
Set #index = #index + 1
END
Select * from #TempTable
END
Just call it an pass table name and your condition that will return one row for example
EXEC [dbo].[Rotat]
#Where = 'UserID = 123456',
#tableName = 'Users'
If you want a very quick technique just for viewing data transposed (as your question seems to suggest), try copying and pasting the output from the results grid into Excel, then copy the Excel data and use Paste Special to Transpose the output.