Add Row Values as Columns to Existing Table - sql-server

It seems like the answer for me lies somewhere within PIVOT and dynamic SQL but I can't put the pieces together. I have the following table.
FieldId InternalFieldName FieldLabel
1 RepairableSpare_1 CField0
6 Equipment_6 CField1
7 Equipment_7 CField2
8 Equipment_8 CField3
9 Equipment_9 CField4
I need to add the values in the FieldLabel column, as their own columns in another table.
End goal would be:
OtherTableID OtherTableColumnA CField0 CField1 CField2 CField3 CField4
ID1 ColumnValue VALUE VALUE VALUE VALUE VALUE
I have a third table that I can use to populate the VALUES in those CField columns, I just can't figure out how to get them as columns in the OtherTable.
EDIT
I've attached an image of the tables I'm working with and text information below.
CustomField Table
FieldId InternalFieldName FieldLabel
6 Equipment_6 CustomField1
7 Equipment_7 CustomField2
8 Equipment_8 CustomField3
9 Equipment_9 CustomField4
Equipment Table
EquipmentId EquipmentNo
7362 ..12
8696 ..12_COPY2
Desired Table
EquipmentId EquipmentNo CustomField1 CustomField2 CustomField3 CustomField4
7362 ..12
8696 ..12_COPY2
Important note, the number of custom fields is not static.
EDIT2
I thought I could figure it out from a certain point, but it looks like that was not the (big shout out to D-shih for sticking with me) case. Below I've included the other table I'll need to work with that I thought I could figure out myself.
I have 3 tables:
CustomField Table
FieldId InternalFieldName FieldLabel
6 Equipment_6 CustomField1
7 Equipment_7 CustomField2
8 Equipment_8 CustomField3
9 Equipment_9 CustomField4
CustomFieldRelationshipTable
FieldValueId FieldId EquipmentId FieldValue
66 6 7431 True
67 7 7431 1900-01-01
68 8 7431 1900-01-01
69 9 7431 NULL
Equipment Table
EquipmentId EquipmentNo
7431 ..12
Desired Table
EquipmentId EquipmentNo CustomField1 CustomField2 CustomField3 CustomField4
7431 ..12 True 1900-01-01 1900-01-01 NULL

I think you can try to use CROSS APPLY with condition aggregate function.
and execute by dynamic SQL.
CREATE TABLE CustomField(
FieldId INT,
InternalFieldName VARCHAR(50),
FieldLabel VARCHAR(50)
);
INSERT INTO CustomField VALUES (6,'Equipment_6','CustomField1');
INSERT INTO CustomField VALUES (7,'Equipment_7','CustomField2');
INSERT INTO CustomField VALUES (8,'Equipment_8','CustomField3');
INSERT INTO CustomField VALUES (9,'Equipment_9','CustomField4');
CREATE TABLE Equipment(
EquipmentId INT,
EquipmentNo VARCHAR(50)
);
INSERT INTO Equipment VALUES (7362,'..12');
INSERT INTO Equipment VALUES (8696,'..12_COPY2');
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',max(case when FieldLabel = ''' + FieldLabel + ''' then InternalFieldName end) ' + QUOTENAME(FieldLabel)
FROM CustomField
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set #query = 'SELECT EquipmentId,EquipmentNo,'+#cols+'
FROM
(
SELECT *
FROM CustomField
) ta CROSS APPLY
(
SELECT *
FROM Equipment
) tb
GROUP BY EquipmentId,
EquipmentNo
'
EXECUTE(#query)
sqlfiddle
if you want to let CustomField be the empty string you just modify the case when
SET #cols = STUFF((SELECT distinct ',max(case when FieldLabel = '''' then InternalFieldName end) ' + QUOTENAME(FieldLabel)
FROM CustomField
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
sqlfiddle

Related

SQL Server Dynamic Pivot Table - Column Name Duplicate

I am attempting to Pivot a table passed in as a UDT.. Column 1 will have duplicate values and Column 2 will have different values (example below). I am hoping for the Column Name to be set as Phone Number and the two Values under the Phone Number column.
DECLARE #query AS NVARCHAR(MAX) = '';
--Temp Table to act as UDT for ease of testing
DECLARE #udt TABLE (DatabaseFieldName nvarchar(50), Value nvarchar(50))
INSERT INTO #udt VALUES('PhoneNumber','01234567890')
INSERT INTO #udt VALUES('PhoneNumber','09876543210')
--Preview of table before Pivot
select * from #udt
CREATE TABLE #temp
(
DatabaseFieldName nvarchar(50),
Value nvarchar(50)
)
INSERT INTO #temp
SELECT DatabaseFieldName, Value
FROM #udt
SELECT #cols = #cols + QUOTENAME(DatabaseFieldName) + ',' FROM (select distinct DatabaseFieldName from #temp) as temp
SELECT #cols = substring(#cols, 0, len(#cols)) -- Trims ',' at the end
SET #query =
'
SELECT * FROM
(
SELECT DatabaseFieldName, Value
FROM #temp
) AS SRC
PIVOT
(
MIN(Value) for DatabaseFieldName in (' + #cols + ')
) AS PivotTable';
execute(#query)
DROP TABLE #temp
Example of current & desired results
Data as it comes in:
DatabaseFieldName | Value
--------------------------------
PhoneNumber | 01234567890
PhoneNumber | 09876543210
Outcome I am hoping to get:
PhoneNumber
------------
01234567890
09876543210
What I am currently getting:
PhoneNumber
------------
01234567890
At the moment the second number is being ignored due to the use of distinct in the select statement, however an error is thrown if distinct is not used.
Are all the values that you want in the pivoted column PhoneNumbers? If so, you can just select the phone numbers themselves with an alias. E.g
SELECT Value As PhoneNumber
FROM (either #UDT or #temp)
WHERE DatabaseFieldName = 'PhoneNumber'
Unless there is a requirement I'm missing here, this would do everything you want it to.
It is not due to DISTINCT, it is because of using MIN(Value) , it gets the first one.
Let's say you had another set of rows
INSERT INTO #udt VALUES('Name','Hello')
INSERT INTO #udt VALUES('Name','Test')
Now the result set of your dynamic SQL will look like this.
Name PhoneNumber
Hello 01234567890
Having said that PIVOT can be used only with aggregate functions, you will get error if MIN is removed. You might have to think of other options for getting desired results such as using case if needed for multiple fields
SELECT CASE WHEN DatabaseFieldName = 'PhoneNumber' THEN Value END AS PhoneNumber,
CASE WHEN DatabaseFieldName = 'Name' THEN Value END AS Name
FROM #udt

How to map row results from one table as headers for another table in a query [duplicate]

I have read the stuff on MS pivot tables and I am still having problems getting this correct.
I have a temp table that is being created, we will say that column 1 is a Store number, and column 2 is a week number and lastly column 3 is a total of some type. Also the Week numbers are dynamic, the store numbers are static.
Store Week xCount
------- ---- ------
102 1 96
101 1 138
105 1 37
109 1 59
101 2 282
102 2 212
105 2 78
109 2 97
105 3 60
102 3 123
101 3 220
109 3 87
I would like it to come out as a pivot table, like this:
Store 1 2 3 4 5 6....
-----
101 138 282 220
102 96 212 123
105 37
109
Store numbers down the side and weeks across the top.
If you are using SQL Server 2005+, then you can use the PIVOT function to transform the data from rows into columns.
It sounds like you will need to use dynamic sql if the weeks are unknown but it is easier to see the correct code using a hard-coded version initially.
First up, here are some quick table definitions and data for use:
CREATE TABLE yt
(
[Store] int,
[Week] int,
[xCount] int
);
INSERT INTO yt
(
[Store],
[Week], [xCount]
)
VALUES
(102, 1, 96),
(101, 1, 138),
(105, 1, 37),
(109, 1, 59),
(101, 2, 282),
(102, 2, 212),
(105, 2, 78),
(109, 2, 97),
(105, 3, 60),
(102, 3, 123),
(101, 3, 220),
(109, 3, 87);
If your values are known, then you will hard-code the query:
select *
from
(
select store, week, xCount
from yt
) src
pivot
(
sum(xcount)
for week in ([1], [2], [3])
) piv;
See SQL Demo
Then if you need to generate the week number dynamically, your code will be:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Week)
from yt
group by Week
order by Week
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT store,' + #cols + ' from
(
select store, week, xCount
from yt
) x
pivot
(
sum(xCount)
for week in (' + #cols + ')
) p '
execute(#query);
See SQL Demo.
The dynamic version, generates the list of week numbers that should be converted to columns. Both give the same result:
| STORE | 1 | 2 | 3 |
---------------------------
| 101 | 138 | 282 | 220 |
| 102 | 96 | 212 | 123 |
| 105 | 37 | 78 | 60 |
| 109 | 59 | 97 | 87 |
This is for dynamic # of weeks.
Full example here:SQL Dynamic Pivot
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName= ISNULL(#ColumnName + ',','') + QUOTENAME(Week)
FROM (SELECT DISTINCT Week FROM #StoreSales) AS Weeks
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT Store, ' + #ColumnName + '
FROM #StoreSales
PIVOT(SUM(xCount)
FOR Week IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
I've achieved the same thing before by using subqueries. So if your original table was called StoreCountsByWeek, and you had a separate table that listed the Store IDs, then it would look like this:
SELECT StoreID,
Week1=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=1),
Week2=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=2),
Week3=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=3)
FROM Store
ORDER BY StoreID
One advantage to this method is that the syntax is more clear and it makes it easier to join to other tables to pull other fields into the results too.
My anecdotal results are that running this query over a couple of thousand rows completed in less than one second, and I actually had 7 subqueries. But as noted in the comments, it is more computationally expensive to do it this way, so be careful about using this method if you expect it to run on large amounts of data .
This is what you can do:
SELECT *
FROM yourTable
PIVOT (MAX(xCount)
FOR Week in ([1],[2],[3],[4],[5],[6],[7])) AS pvt
DEMO
I'm writing an sp that could be useful for this purpose, basically this sp pivot any table and return a new table pivoted or return just the set of data, this is the way to execute it:
Exec dbo.rs_pivot_table #schema=dbo,#table=table_name,#column=column_to_pivot,#agg='sum([column_to_agg]),avg([another_column_to_agg]),',
#sel_cols='column_to_select1,column_to_select2,column_to_select1',#new_table=returned_table_pivoted;
please note that in the parameter #agg the column names must be with '[' and the parameter must end with a comma ','
SP
Create Procedure [dbo].[rs_pivot_table]
#schema sysname=dbo,
#table sysname,
#column sysname,
#agg nvarchar(max),
#sel_cols varchar(max),
#new_table sysname,
#add_to_col_name sysname=null
As
--Exec dbo.rs_pivot_table dbo,##TEMPORAL1,tip_liq,'sum([val_liq]),sum([can_liq]),','cod_emp,cod_con,tip_liq',##TEMPORAL1PVT,'hola';
Begin
Declare #query varchar(max)='';
Declare #aggDet varchar(100);
Declare #opp_agg varchar(5);
Declare #col_agg varchar(100);
Declare #pivot_col sysname;
Declare #query_col_pvt varchar(max)='';
Declare #full_query_pivot varchar(max)='';
Declare #ind_tmpTbl int; --Indicador de tabla temporal 1=tabla temporal global 0=Tabla fisica
Create Table #pvt_column(
pivot_col varchar(100)
);
Declare #column_agg table(
opp_agg varchar(5),
col_agg varchar(100)
);
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#table) AND type in (N'U'))
Set #ind_tmpTbl=0;
ELSE IF OBJECT_ID('tempdb..'+ltrim(rtrim(#table))) IS NOT NULL
Set #ind_tmpTbl=1;
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#new_table) AND type in (N'U')) OR
OBJECT_ID('tempdb..'+ltrim(rtrim(#new_table))) IS NOT NULL
Begin
Set #query='DROP TABLE '+#new_table+'';
Exec (#query);
End;
Select #query='Select distinct '+#column+' From '+(case when #ind_tmpTbl=1 then 'tempdb.' else '' end)+#schema+'.'+#table+' where '+#column+' is not null;';
Print #query;
Insert into #pvt_column(pivot_col)
Exec (#query)
While charindex(',',#agg,1)>0
Begin
Select #aggDet=Substring(#agg,1,charindex(',',#agg,1)-1);
Insert Into #column_agg(opp_agg,col_agg)
Values(substring(#aggDet,1,charindex('(',#aggDet,1)-1),ltrim(rtrim(replace(substring(#aggDet,charindex('[',#aggDet,1),charindex(']',#aggDet,1)-4),')',''))));
Set #agg=Substring(#agg,charindex(',',#agg,1)+1,len(#agg))
End
Declare cur_agg cursor read_only forward_only local static for
Select
opp_agg,col_agg
from #column_agg;
Open cur_agg;
Fetch Next From cur_agg
Into #opp_agg,#col_agg;
While ##fetch_status=0
Begin
Declare cur_col cursor read_only forward_only local static for
Select
pivot_col
From #pvt_column;
Open cur_col;
Fetch Next From cur_col
Into #pivot_col;
While ##fetch_status=0
Begin
Select #query_col_pvt='isnull('+#opp_agg+'(case when '+#column+'='+quotename(#pivot_col,char(39))+' then '+#col_agg+
' else null end),0) as ['+lower(Replace(Replace(#opp_agg+'_'+convert(varchar(100),#pivot_col)+'_'+replace(replace(#col_agg,'[',''),']',''),' ',''),'&',''))+
(case when #add_to_col_name is null then space(0) else '_'+isnull(ltrim(rtrim(#add_to_col_name)),'') end)+']'
print #query_col_pvt
Select #full_query_pivot=#full_query_pivot+#query_col_pvt+', '
--print #full_query_pivot
Fetch Next From cur_col
Into #pivot_col;
End
Close cur_col;
Deallocate cur_col;
Fetch Next From cur_agg
Into #opp_agg,#col_agg;
End
Close cur_agg;
Deallocate cur_agg;
Select #full_query_pivot=substring(#full_query_pivot,1,len(#full_query_pivot)-1);
Select #query='Select '+#sel_cols+','+#full_query_pivot+' into '+#new_table+' From '+(case when #ind_tmpTbl=1 then 'tempdb.' else '' end)+
#schema+'.'+#table+' Group by '+#sel_cols+';';
print #query;
Exec (#query);
End;
GO
This is an example of execution:
Exec dbo.rs_pivot_table #schema=dbo,#table=##TEMPORAL1,#column=tip_liq,#agg='sum([val_liq]),avg([can_liq]),',#sel_cols='cod_emp,cod_con,tip_liq',#new_table=##TEMPORAL1PVT;
then Select * From ##TEMPORAL1PVT would return:
Here is a revision of #Tayrn answer above that might help you understand pivoting a little easier:
This may not be the best way to do this, but this is what helped me wrap my head around how to pivot tables.
ID = rows you want to pivot
MY_KEY = the column you are selecting from your original table that contains the column names you want to pivot.
VAL = the value you want returning under each column.
MAX(VAL) => Can be replaced with other aggregiate functions. SUM(VAL), MIN(VAL), ETC...
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(MY_KEY)
from yt
group by MY_KEY
order by MY_KEY ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ID,' + #cols + ' from
(
select ID, MY_KEY, VAL
from yt
) x
pivot
(
sum(VAL)
for MY_KEY in (' + #cols + ')
) p '
execute(#query);
select * from (select name, ID from Empoyee) Visits
pivot(sum(ID) for name
in ([Emp1],
[Emp2],
[Emp3]
) ) as pivottable;
Just give you some idea how other databases solve this problem. DolphinDB also has built-in support for pivoting and the sql looks much more intuitive and neat. It is as simple as specifying the key column (Store), pivoting column (Week), and the calculated metric (sum(xCount)).
//prepare a 10-million-row table
n=10000000
t=table(rand(100, n) + 1 as Store, rand(54, n) + 1 as Week, rand(100, n) + 1 as xCount)
//use pivot clause to generate a pivoted table pivot_t
pivot_t = select sum(xCount) from t pivot by Store, Week
DolphinDB is a columnar high performance database. The calculation in the demo costs as low as 546 ms on a dell xps laptop (i7 cpu). To get more details, please refer to online DolphinDB manual https://www.dolphindb.com/help/index.html?pivotby.html
Pivot is one of the SQL operator which is used to turn the unique data from one column into multiple column in the output. This is also mean by transforming the rows into columns (rotating table). Let us consider this table,
If I want to filter this data based on the types of product (Speaker, Glass, Headset) by each customer, then use Pivot operator.
Select CustmerName, Speaker, Glass, Headset
from TblCustomer
Pivot
(
Sum(Price) for Product in ([Speaker],[Glass],[Headset])
) as PivotTable

Dynamic Pivot multiple columns in SQL Server

I have a table like this
Id Name FromAddress ToAddress
1 Joey ABC JKL
2 Joey DEF MNP
3 Joey GHI OQR
I am looking for the following output with dynamic pivot in SQL Server
Name FromAdrs1 FromAdrs2 FromAdrs3 ToAdrs1 ToAdrs2 ToAdrs3
Joey ABC DEF GHI JKL MNP OQR
Note: The number of rows changes based on the Id value, so I am trying to get the output using dynamic Pivot.
Here is the code that I tried, it's looks like it is correct, but throwing me an error.
IF OBJECT_ID('temp..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
Id INT, Name VARCHAR(10), FromAddress VARCHAR(10), ToAddress VARCHAR(10)
)
INSERT INTO #temp VALUES (1, 'Joey', 'ABC', 'JKL'), (2, 'Joey', 'DEF', 'MNP'), (3, 'Joey', 'GHI', 'OQR')
--SELECT * FROM #temp
DECLARE #colsFrom AS NVARCHAR(MAX),
#colsTo AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #colsFrom = STUFF((SELECT distinct ',' + QUOTENAME(CONVERT(VARCHAR(2), t.id) + 'From')
FROM #temp t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #colsTo = STUFF((SELECT distinct ',' + QUOTENAME(CONVERT(VARCHAR(2), t.id) + 'To')
FROM #temp t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *, ' + #colsFrom + ', ' + #colsTo + ' from
(
select *
from #temp
) T
PIVOT
(
max(FromAddress)
for Id in (REPLACE('''+#colsFrom+''',''From'',''''))
) p
PIVOT
(
max(ToAddress)
for Id in (REPLACE('''+#colsTo+''',''To'',''''))
) Q'
execute(#query)
DROP TABLE #temp
Any help is appreciated. Thank you all for your time.
Edit: This is the error
I believe the problem is the IN () expression in the PIVOTs. The column list explicitly has to be a list of fields names, not a function and not a list of varchar literals or function values. You've got a REPLACE() function in there. The engine expects to be looking for a field named [REPLACE] and then gets confused by the open parentheses that shows up.
This is valid (square brackets for emphasis):
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
([Emp1], [Emp2], [Emp3], [Emp4], [Emp5])
)AS unpvt;
This is not:
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
('Emp1', 'Emp2', 'Emp3', 'Emp4', 'Emp5')
)AS unpvt;
And this is not valid:
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(REPLACE('Emp1','1','A'), REPLACE('Emp2','2','B'))
)AS unpvt;
Replace the execute(#query) with a select #query or print #query to see the query your code generated and troubleshoot the syntax in a query analyzer that way. Then work backwards.
You want to do the REPLACE() at the same level you're building the query. The query that ends up in the #query variable should already have the column names fixed.
Alternately, you could generate #colsFromLabels, #colsToLabels, #colsFrom and #colsTo with the former two have the 'from' and to bits added and the latter two just being column names.
Your desired output is a little gross as far as square bracket escaping, too.
ok, I created a temp table to do some testing on. The solution requires an unpivot first. I recommend running with/without the extra test data to get a sense of some other behaviors that surround this solution -- the weirdness that comes with the MAX aggregation and lack of new rows that you might have expected when changing the value in 'name'.
GL. Hope it helps.
-------------------------
-- Some test data here
CREATE table #addresses ( Id int, Name varchar(5), FromAddress varchar(5), ToAddress varchar(5))
insert into #addresses(id, Name, FromAddress, ToAddress) Values
(1,'Joey', 'ABC', 'JKL')
, (2,'Joey', 'DEF', 'MNO')
, (3,'Joey', 'GHI', 'PQR')
, (4,'Spike', 'XXX', 'YYY')
, (1,'Spike', 'QQQ', 'RRR')
-------------------------
-- Solution starts here. create a temp table and unpivot your data into it.
-- Your initial technique of does not work, PIVOT only supports one aggregation
CREATE table #unpvt(RowColCode varchar(20), vals varchar(20))
Insert into #unpvt
SELECT ColCode + '_' + Cast(ID as varchar(2)) as RowColCode, vals
FROM #addresses a
UNPIVOT
(vals for ColCode in (Name,FromAddress,ToAddress)) c
-------------------------
-- Read the temp table for a column list
declare #ColList nvarchar(max)
set #ColList = STUFF((
SELECT distinct ',[' + t.RowColCode + ']'
FROM #unpvt t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
-------------------------
-- 're pivot' the data using your new column list
declare #qry varchar(max)
set #qry = '
select *
from
#unpvt
PIVOT(
MAX(vals)
FOR RowColCode in (' +#ColList + ')
) rslt
'
execute(#qry)

Trying to pivot multiple columns in T-SQL

I have a query which dynamically generates different number of rows, with varying ID column values. I need to be able to PIVOT this into a columnar result. My current data result is below.
ID Caption FieldName FieldType
--- --------- ------------ ------------
10 Caption 1 Field Name 1 Field Type 1
11 Caption 2 Field Name 2 Field Type 2
12 Caption 3 Field Name 3 Field Type 3
20 Caption 4 Field Name 4 Field Type 4
30 Caption 5 Field Name 5 Field Type 5
My desired result is
10 11 12 20 30
-------- ---------- --------- --------- ---------
Caption 1 Caption 2 Caption 3 Caption 4 Caption 5
Field Name 1 Field Name 2 Field Name 3 Field Name 4 Field Name 5
Field Type 1 Field Type 2 Field Type 3 Field Type 4 Field Type 5
Please note that the values 10, 11, 12, 20 and 30 can change to be something else, so I understand that I need to do some dynamic sql. I want to avoid using CURSORS if possible.
Any suggestions are welcome. Please excuse the formatting
2005 Version
Declare #SQL varchar(max)
Select #SQL = stuff((Select Distinct ',' + QuoteName(ID)+'=max(case when Item='+cast(ID as varchar(25))+' then Value else null end)' From YourTable Order By 1 For XML Path('') ),1,1,'')
Select #SQL = '
Select [Seq],'+#SQL +'
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Group By Seq
Order By Seq
'
Exec(#SQL);
Returns
If you don't mind going dynamic
I'm hesitant to remove SEQ (the first column of the results). You can remove [SEQ], from the final query, but I am not sure it would maintain the proper sequence on a larger data set.
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName(ID) From YourTable Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select [Seq],' + #SQL + '
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Pivot (max(value) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
EDIT - With SEQ Removed from the final Select

Spliting string in Sql and storing in temp table

I am facing a problem since 3 days, Actually, I am working on SSRS where stored procedure expects multiple rows of parameters i.e splitting rows as ';' and column as ','. So actually I want to split the column with ',' and ';' as rows and will further insert into the temp table. Any help will be really appreciated.
EG: data coming in stored procedure as a parameter from app:
101,1,1,1,5;
102,1,1,1,4;
103,1,1,1,3;
accepted as Varchar in stored procedure.
Now wants to split the data as ';' once and then with ',' for every row.
If i correctly understood the question, data is required in rows and columns based on string,split the column with ',' and ';' as rows
DECLARE #PARAM_STRING VARCHAR(100)='101,1,1,1,5; 102,1,1,1,4; 103,1,1,1,3;11,11,11,11,11;12,12,12,12,12;'
DECLARE #DYNAMIC_QUERY VARCHAR(MAX)
DECLARE #TABLE TABLE(ID INT,DATA VARCHAR(MAX))
INSERT INTO #TABLE
SELECT 1 ID, 'SELECT '+DATA FROM (
SELECT A.B.value('.','VARCHAR(50)')DATA FROM
(SELECT CAST('<A>'+REPLACE(#PARAM_STRING,';','</A><A>')+'</A>' AS XML)COL)T
CROSS APPLY T.COL.nodes('/A') AS A(B))F WHERE DATA<>''
SELECT #DYNAMIC_QUERY=STUFF((SELECT ' UNION ' + CAST(DATA AS VARCHAR(MAX)) [text()]FROM #TABLE WHERE ID = t.ID
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,7,' ')
FROM #TABLE t GROUP BY ID
EXECUTE(#DYNAMIC_QUERY)
Result :
(No column name) (No column name) (No column name) (No column name) (No column name)
11 11 11 11 11
12 12 12 12 12
101 1 1 1 5
102 1 1 1 4
103 1 1 1 3
there are many approaches to do this using xml, cte or loop. below is with xml,
DECLARE #ParamStr VARCHAR(500) = '101,1,1,1,5; 102,1,1,1,4; 103,1,1,1,3;'
DECLARE #x XML
SELECT #x = CAST('<R><SemiCol><Comma>'+ REPLACE(REPLACE(#ParamStr,';','</Comma></SemiCol><SemiCol><Comma>'),',','</Comma><Comma>')+ '</Comma></SemiCol></R>' AS XML)
SELECT t.value('.', 'int') AS inVal
FROM #x.nodes('R/SemiCol/Comma') AS x(t)
WHERE LEN(t.value('.', 'varchar(10)')) > 0

Resources