Pivot Rows to Column with SUM if Hours between two Time Value - sql-server

Im using MS SQL Server 2008
Table name is tblDateTimeLog:
ID INT(AI)
RecordID INT
DateLog DATE
TimeLog TIME
DetachmentCode INT
EntryDate DATETIME
IsDeleted BIT
UserID VARCHAR(50)
I have a table containing this:
RecordID | DateLog | TimeLog
11 | 2013-06-01 | 07:59:00
11 | 2013-06-01 | 19:01:00
11 | 2013-06-02 | 07:57:00
11 | 2013-06-02 | 19:03:00
11 | 2013-06-03 | 07:49:00
11 | 2013-06-03 | 19:11:00
14 | 2013-06-04 | 08:01:00
14 | 2013-06-04 | 19:03:00
14 | 2013-06-05 | 07:52:00
14 | 2013-06-05 | 19:02:00
One Record ID can have multiple TimeLog on the same DateLog
Now I want it to show like this:
The Dates as columns and the Total No. of Hours between MIN(TimeLog) and MAX(TimeLog)
RecordID | 2013-06-01 | 2013-06-02 | 2013-06-03 | 2013-06-04 | 2013-06-05
11 | 11:02:00 | 11:06:00 | 11:22:00 | NULL | NULL
14 | NULL | NULL | NULL | 11:02:00 | 11:10:00
As per Mikael's Answer, this works but as I understand his query, this returns MIN(TimeLog):
DECLARE #SQL NVARCHAR(MAX)
DECLARE #ColumnList NVARCHAR(MAX)
SELECT #ColumnList =
STUFF
(
(
SELECT DISTINCT ','+QUOTENAME(DateLog)
FROM TESTPIS.dbo.tblDateTimeLog
WHERE IsDeleted=0 AND DateLog >= '2013-06-15' AND DateLog <= '2013-06-30'
ORDER BY 1
FOR XML PATH('')
), 1, 1, ''
)
SET #SQL = 'SELECT P.RecordID, '+#ColumnList+'
FROM
(
SELECT RecordID, TimeLog, DateLog FROM TESTPIS.dbo.tblDateTimeLog WHERE isDeleted=0
) AS T
PIVOT
(
MIN(TimeLog) FOR DateLog IN ('+#ColumnList+')
) as P'
EXEC (#SQL)
What I want to return is like DATEDIFF(MINUTES,MIN(TimeLog),MAX(TimeLog)
I tried replacing the MIN(TimeLog) in the query with this
SUM(DATEDIFF(MINUTES,MIN(TimeLog),MAX(TimeLog))
However, I got this error
Incorrect syntax near '('.

select P.RecordID,
P.[2013-06-01],
P.[2013-06-02],
P.[2013-06-03],
P.[2013-06-04],
P.[2013-06-05]
from (
select RecordID,
TimeLog,
DateLog
from YourTable
) as T
pivot(min(TimeLog) for DateLog in ([2013-06-01],
[2013-06-02],
[2013-06-03],
[2013-06-04],
[2013-06-05])) as P
To build the query dynamically you have to first figure out what the column list should contain.
select distinct DateLog
from YourTable
order by 1
The result from that query has to be turned into a comma separated list and since numbers like that is invalid column names you can use quotename() to enclose the value in [].
To build the comma separated list of column you can use for xml path('').
select stuff((select distinct ','+quotename(DateLog)
from YourTable
order by 1
for xml path('')), 1, 1, '')
stuff() is there to remove the first comma.
Then you just need to put it all together and execute the query you have built.
declare #SQL nvarchar(max)
declare #ColumnList nvarchar(max)
select #ColumnList = stuff((select distinct ','+quotename(DateLog)
from YourTable
order by 1
for xml path('')), 1, 1, '')
set #SQL = '
select P.RecordID, '+#ColumnList+'
from (
select RecordID,
TimeLog,
DateLog
from YourTable
) as T
pivot(min(TimeLog) for DateLog in ('+#ColumnList+')) as P'
exec (#SQL)
SQL Fiddle
Update
To get the diff between max and min timelog value for each day you can do a group by on RecordID and DateLog in the derived table and calculate the diff in seconds between min and max and use that value to calculate a new time value using dateadd.
select P.RecordID,
P.[2013-06-01],
P.[2013-06-02],
P.[2013-06-03],
P.[2013-06-04],
P.[2013-06-05]
from (
select RecordID,
dateadd(second, datediff(second, min(TimeLog), max(TimeLog)), convert(time(0), '00:00')) as TimeDiff,
DateLog
from YourTable
group by RecordID,
DateLog
) as T
pivot(min(TimeDiff) for DateLog in ([2013-06-01],
[2013-06-02],
[2013-06-03],
[2013-06-04],
[2013-06-05])) as P
Dynamic version:
declare #SQL nvarchar(max)
declare #ColumnList nvarchar(max)
select #ColumnList = stuff((select distinct ','+quotename(DateLog)
from YourTable
order by 1
for xml path('')), 1, 1, '')
set #SQL = '
select P.RecordID, '+#ColumnList+'
from (
select RecordID,
dateadd(second, datediff(second, min(TimeLog), max(TimeLog)), convert(time(0), ''00:00'')) as TimeDiff,
DateLog
from YourTable
group by RecordID,
DateLog
) as T
pivot(min(TimeDiff) for DateLog in ('+#ColumnList+')) as P'
exec (#SQL)
SQL Fiddle

Try this one -
Query:
IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
RecordID INT
, DateLog DATETIME
, TimeLog TIME
)
INSERT INTO #temp (RecordID, DateLog, TimeLog)
VALUES
(11, '2013-06-01', '08:00:00'), (11, '2013-06-02', '09:00:00'),
(11, '2013-06-03', '10:00:00'), (11, '2013-06-04', '11:00:00'),
(11, '2013-06-05', '12:00:00'), (14, '2013-06-01', '13:00:00'),
(14, '2013-06-02', '14:00:00'), (14, '2013-06-03', '15:00:00'),
(14, '2013-06-04', '16:00:00')
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = 'SELECT *
FROM (
SELECT DateLog, RecordID, tt = CAST(TimeLog AS VARCHAR(8))
FROM #temp
) src
PIVOT (
MAX(tt)
FOR DateLog IN (' + STUFF((
SELECT ', [' + CONVERT(VARCHAR(10), DateLog, 120) + ']'
FROM #temp
GROUP BY DateLog
ORDER BY DateLog
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')
) p'
PRINT #SQL
EXEC sys.sp_executesql #SQL
Output:
SELECT *
FROM (
SELECT DateLog, RecordID, tt = CAST(TimeLog AS VARCHAR(8))
FROM #temp
) src
PIVOT (
MAX(tt)
FOR DateLog IN ([2013-06-01], [2013-06-02], [2013-06-03], [2013-06-04], [2013-06-05])
) p
Results:
RecordID 2013-06-01 2013-06-02 2013-06-03 2013-06-04 2013-06-05
----------- ---------- ---------- ---------- ---------- ----------
11 08:00:00 09:00:00 10:00:00 11:00:00 12:00:00
14 13:00:00 14:00:00 15:00:00 16:00:00 NULL
Update with results:

Related

How to use stuff on entire columns of the table:

I executed the below query and it executed well :-
SELECT table2id, stuff((select CHAR(13) + table1name from table1 where table1id=table2.table2id FOR XML PATH (''), TYPE
).value('.', 'varchar(max)')
, 1, 1, '')
from table2 where table2id=117 group by id;
But when I am using count(*) , like in below query :-
SELECT table2id, stuff((select CHAR(13) + count(*) from table1 where table1id=table2.table2id FOR XML PATH (''), TYPE
).value('.', 'varchar(max)')
, 1, 1, '')
from table2 where table2id=117 group by id;
I am getting the below error:
Msg 245, Level 16, State 1, Line 19
Conversion failed when converting the varchar value '
' to data type int.
Now how can I stuff all the columns in table1 ? could anyone help !
I want my result like below:-
table2id | table1name | table1id | table1color
------------------------------------------------------
117 | jon, jack | 117,117 | blue,red
( I am adding my sample data for table1 and table2) :-
table1:
table1id | table1name | table1color | table1city | table1animal |...(I
have 25 columns like this !)
--------------------------------------------------------------
117 | jon | blue | city1 | animal1
117 | jack | red | city2 | animal2
table2:
table2id | table2uniqueid
-------------------------
117 | asbn6383hhh3j3837
118 | kf9s8sujfu6df5d7j
This has nothing to do with stuff.
The reason you get the error is this:
count(*) returns an int. char(13) is a char. Whenever you try to do int + char SQL Server will try to implicitly convert the char to an int. Naturally, char(13) cannot be converted to an int.
What you need to to explicitly convert the count(*) to varchar:
SELECT table2id, stuff(
(
select CHAR(13) + cast(count(*) as varchar(10))
from table1
where table1id=table2.table2id
FOR XML PATH (''), TYPE).value('.', 'varchar(max)'), 1, 1, '')
from table2
where table2id=117
group by id;
Try this code it will helps you by using Dynamic Sql
Firstly i created Two physical Tables with sample data
CREATE TABLE Table1 (table1id INT , table1name Varchar(100) , table1color Varchar(100) , table1city Varchar(100) , table1animal Varchar(100))
INSERT INTO Table1
SELECT 117, 'jon' , 'blue' , 'city1' , 'animal1' UNION ALL
SELECT 117, 'jack', 'red' , 'city2' , 'animal2'
CREATE TABLE Table2( table2id INT, table2uniqueid nvarchar(1000))
INSERT INTO Table2
SELECT 117,'asbn6383hhh3j3837' Union all
SELECT 118,'kf9s8sujfu6df5d7j'
Dynamic Sql code to get the expected result
SET NOCOUNT ON
IF OBJECT_ID('Tempdb..#TEMP') IS NOT NULL
DROP TABLE #TEMP
CREATE TABLE #TEMP(ID INT IDENTITY ,Query nvarchar(max))
IF OBJECT_ID('Tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2
CREATE TABLE #TEMP2(ID INT IDENTITY ,Query nvarchar(max))
DECLARE #MinID INT,
#MaxID INT,
#Sql nvarchar(max),
#Getcolumn nvarchar(max),
#Sql2 nvarchar(max),
#CteSql nvarchar(max),
#CteSql2 nvarchar(max),
#FullSql nvarchar(max)
DEClare #COlumn Table
(
ID INT IDENTITY,
COlumnname varchar(100)
)
INSERT into #COlumn(COlumnname)
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS Where TABLE_NAME='Table1'
SELECT #MinID=MIn(Id),#MaxID=MAX(ID)FRom #COlumn
While (#MinID <=#MaxID)
Begin
SELECT #Getcolumn=COlumnname From #COlumn WHERE ID=#MinID
SET #Sql=N' STUFF((SELECT '', ''+ CAST('+#Getcolumn +' AS VARCHAR(5))
FROM cte AS i
WHERE i.table1id=o.table1id For XML PATH ('''')),1,1,'''') AS '+#Getcolumn
INSERT INTO #TEMP(Query)
SELECT #Sql
SET #MinID=#MinID+1
END
SELECT DISTINCT #Sql2=
STUFF((SELECT ', '+ CAST(Query AS nvarchar(max)) FROM #TEMP i For Xml Path(''), type
).value('.', 'nvarchar(max)')
, 1, 2, '')
FROM #TEMP o
SET #Sql2=#Sql2 +' FRom Cte o'
SET #CteSql= 'SELECT Top 1 '+''' ;With cte
AS
(SELECT T2.table2id,''+ STUFF((SELECT '', ''+''T1.''+COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME=''Table1'' For XML PATH ('''')),1,1,'''') +'' From Table2 T2
LEFT JOIN Table1 T1
On T1.table1id=t2.table2id )''' +'+CHAR(13)+CHAR(10)+'+'''SELECT DISTINCT table2id,''
FROM INFORMATION_SCHEMA.COLUMNS Where TABLE_NAME=''Table1'''
INSERT INTO #TEMP2(Query)
EXECUTE(#CteSql)
SELECT #CteSql2= Query From #TEMP2
SET #FullSql=#CteSql2+#Sql2
PRINT #FullSql
EXEC(#FullSql)
SET NOCOUNT OFF
Result After Running the Query
table2id table1id table1name table1color table1city table1animal
---------------------------------------------------------------------------------------
117 117, 117 jon, jack blue, red city1, city2 anima, anima
118 NULL NULL NULL NULL NULL

Query to retrieve column values as rows from table which has duplicate rows in SQL Server 2008

I have a table which has records in the following format:
OrderID | CategoryID | Percentage
-----------------------------------------
Order1 1 50
Order1 2 100
Order1 3 70
Order2 1 85
Order2 2 75
Order2 3 100
Order3 1 50
Order3 2 60
Order3 3 80
Each order has multiple categories and each category has a percentage corresponding to that order.
I want to display it in the following format:
OrderID | Category1_% | Category2_% | Category3_%
-------------------------------------------------------
Order1 50 100 70
Order2 85 75 100
Order3 50 60 80
How do I write a query in SQL Server 2008 to retrieve percentages for each category of each (distinct) order? Please help.
Edit:
Orders table
ID | StartDate
--------------------
Order1 1/1/2016
Order2 10/1/2015
Order3 10/5/2016
The query which I executed is:
Declare #SQL varchar(max)
Declare #startDate datetime
set #startDate='1/1/2015'
Declare #endDate datetime
set #endDate= '10/1/2016'
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From OrdersData Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from OrdersData join Orders on Orders.ID =OrdersData.OrderID
WHERE Orders.StartDate >= '+ ***convert(nvarchar(25), #startDate, 121)*** + ' and GCWR.StartDate <= '+ ***convert(nvarchar(25), #endDate, 121)*** +') A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
When I execute, I get an error 'Incorrect syntax near '00'.' How do I call the datetime values in the above query to display the results? Please let me know.
Just in case you need to go dynamic
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From YourTable Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from YourTable) A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Edit - Updated with StartDate
Declare #Date1 datetime = '2015-01-01'
Declare #Date2 datetime = '2016-10-01'
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName('Category'+cast(CategoryID as varchar(25))+'_%') From YourTable Where cast(StartDate as date) between #Date1 and #Date2 Order By 1 For XML Path('')),1,1,'')
Select #SQL = 'Select [OrderID],' + #SQL +'
From (Select OrderID,Percentage,Item=''Category''+cast(CategoryID as varchar(25))+''_%'' from YourTable Where cast(StartDate as date) between '''+convert(varchar(10),#Date1,120)+''' and '''+convert(varchar(10),#Date2,120)+''') A
Pivot (max(Percentage) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Give this a try:
Select OrderID, [1] as [Category1_%], [2] as [Category2_%],[3] as [Category3_%]
From [TableName]
PIVOT (MAX([Percentage]) FOR [CategoryID] IN ([1],[2],[3])) myPivot
This assumes that you know all the possible values in the categoryID field and that each CategoryID an OrderID combination has a single percentage value.

How do I sort a SQL Server 2008 pivot result columns and rows?

I'm using This to get pivot results for a table. But I want the resulting columns and rows both in a specific order. So the rows would be sorted by CDATE and the columns would be CDATE, BALANCE, then the DATE columns.
CDATE | BALANCE | 04-2007 | 05-2007 | 06-2007 | TRANS TOT
2003-01-15 | 5000 | 60 | 0 | 0 | 60
2003-02-15 | 4000 | 40 | 0 | 0 | 40
2003-03-15 | 5500 | 20 | 15 | 15 | 50
I edited the answer in the link you provided in your question to achieve the ordering issue. Just add ORDER BY clause to your dynamic query:
create table temp
(
date datetime,
category varchar(3),
amount money
)
insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('3/1/2012', 'ABC', 1100.00)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.category)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT date, ' + #cols + ' from
(
select date
, amount
, category
from temp
) x
pivot
(
max(amount)
for category in (' + #cols + ')
) p ORDER BY date, ' + #cols
Execute(#query)
drop table temp
OR You can use common table expression to achieve this. like the following:
set #query = 'WITH CTE_1(date, ' + #cols + ') AS (SELECT date, ' + #cols + ' from
(
select date
, amount
, category
from temp
) x
pivot
(
max(amount)
for category in (' + #cols + ')
) p ) SELECT * FROM CTE_1 ORDER BY date, ' + #cols

Simplify Dynamic SQL Pivot Table

I have written a Dynamic Pivot Table Query based on the following. Here is a SQL FIDDLE for reference.
CREATE TABLE TestTable1 ([idnumber] INT, [DataTypeId] INT)
GO
INSERT INTO TestTable1
VALUES (1, 108), (1, 108), (1, 108), (2, 108),
(2, 108), (3, 108), (1, 109),(1, 109),
(1, 110),(2, 110),(1, 111),(4, 108),(4, 108),
(4, 110),(4, 111)
GO
Here is the Dynamic SQL that I wrote
DECLARE #SQL NVARCHAR(MAX),
#Cols NVARCHAR(MAX),
#ColsP NVARCHAR(MAX)
SELECT #Cols = STUFF((select ',
ISNULL([' + CAST([DataTypeId] as varchar(10)) + '], 0) AS ''' + CAST([DataTypeId] as varchar(10)) + ''''
FROM
(
SELECT [DataTypeId] FROM [TestTable1]
GROUP BY [DataTypeId]
HAVING [DataTypeId] <> ''
) AS d
ORDER BY [DataTypeId] FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
-- /////////////THIS IS WHAT I WANT REMOVED ////////////////////
SELECT #ColsP = STUFF((select ',
[' + CAST([DataTypeId] as varchar(10)) + ']'
FROM
(
SELECT [DataTypeId] FROM [TestTable1]
GROUP BY [DataTypeId]
HAVING [DataTypeId] <> ''
) AS d
ORDER BY [DataTypeId] FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
-- /////////////////////////////////////////////////////////////
SET #SQL = 'SELECT idnumber,' + #Cols + '
FROM
(SELECT idnumber, COUNT([DataTypeId]) AS Total, [DataTypeId] FROM [TestTable1]
GROUP BY idnumber, [DataTypeId]
HAVING [DataTypeId] <> ''''
) p
PIVOT
(
SUM(Total) FOR [DataTypeId] IN (' + #ColsP + ')
) AS pvt
ORDER BY pvt.idnumber'
-- print #SQL
EXECUTE( #SQL)
I get the result that I want:
| IDNUMBER | 108 | 109 | 110 | 111 |
|----------|-----|-----|-----|-----|
| 1 | 3 | 2 | 1 | 1 |
| 2 | 2 | 0 | 1 | 0 |
| 3 | 1 | 0 | 0 | 0 |
| 4 | 2 | 0 | 1 | 1 |
But I am sure it can be done better. I would like to remove where I populate the variable #ColsP - SELECT #ColsP = STUFF((select...")
There should be a way where I can create this dynamic code with just one loop through TestTable1. As you can see, I loop through it twice. Once to read what columns to create for the select statement, and once for the PIVOT table.
Here is the code that is generated by the Dynamic SQL:
SELECT idnumber,
ISNULL([108], 0) AS '108',
ISNULL([109], 0) AS '109',
ISNULL([110], 0) AS '110',
ISNULL([111], 0) AS '111'
FROM
(
SELECT idnumber, COUNT([DataTypeId]) AS Total, [DataTypeId]
FROM [TestTable2]
GROUP BY idnumber, [DataTypeId]
HAVING [DataTypeId] <> ''
) p
PIVOT
(
SUM(Total) FOR [DataTypeId] IN ([108], [109], [110], [111])
) AS pvt
ORDER BY pvt.idnumber
You can shorten your code considerably. First, you can just use count to aggregate the data in the PIVOT. There is no need for the inner count to aggregate the data or the HAVING clause. Finally, you only need to create the list of columns once. You could easily improve the code to:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(DataTypeId)
from TestTable1
group by DataTypeId
order by DataTypeId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= N'SELECT idnumber, ' + #cols + N'
from
(
select idnumber, DataTypeId
from TestTable1
) x
pivot
(
count(DataTypeId)
for DataTypeId in (' + #cols + N')
) p '
exec sp_executesql #query;
See SQL Fiddle with Demo. This gives the same result:
| IDNUMBER | 108 | 109 | 110 | 111 |
|----------|-----|-----|-----|-----|
| 1 | 3 | 2 | 1 | 1 |
| 2 | 2 | 0 | 1 | 0 |
| 3 | 1 | 0 | 0 | 0 |
| 4 | 2 | 0 | 1 | 1 |
Try replacing it with this.
SET NOCOUNT ON
IF OBJECT_ID('TestTable1') IS NOT NULL
DROP TABLE TestTable1
GO
CREATE TABLE TestTable1 ([idnumber] INT, [DataTypeId] INT)
GO
INSERT INTO TestTable1 VALUES
(1, 108),(1, 108),(1, 108),(2, 108),(2, 108),
(3, 108),(1, 109),(1, 109),(1, 110),(2, 110),
(1, 111),(4, 108),(4, 108),(4, 110),(4, 111)
DECLARE
#AllColumns NVARCHAR(MAX)
SELECT #AllColumns = ''
SELECT #AllColumns = #AllColumns +
'[' + CAST(DataTypeId as NVARCHAR)+'],'
FROM TestTable1
GROUP BY DataTypeId
SET #AllColumns = LEFT(#AllColumns,LEN(#AllColumns)-1)
PRINT #AllColumns

Multi Column to One Column

I am writing a trigger and I am using inserted
Inserted is a single row
like
ColumnX |ColumnY|ColumnZ|
=========================
A | B |C |
I want to insert results to another table like this
ColumnName |Value|
==================
ColumnX | A |
ColumnY | B |
ColumnZ | C |
I have a lot of tables how can I make this?
UNPIVOT the result set, then insert them:
INSERT INTO Anothertable(Columnname, value)
SELECT Columnname, value
FROM tablename t
UNPIVOT
(
value
FOR ColumnName IN(ColumnX, ColumnY, ColumnZ)
) AS u;
SQL Fiddle Demo
To do this dymaincally:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(Columnname)
FROM table1 t
UNPIVOT
(
value
FOR ColumnName IN(ColumnX, ColumnY, ColumnZ)
) AS u
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SET #query = 'SELECT Columnname, value
FROM table1 t
UNPIVOT
(
value
FOR ColumnName IN( ' + #cols + ' )
) AS u;'
execute(#query);
Updated SQL Fiddle Demo
CREATE TRIGGER TriggerName
ON YourDatabase.TableName
AFTER INSERT
AS
BEGIN
INSERT INTO OtherTable (ColumnX, ColumnY, ColumnZ)
SELECT ColumnX, ColumnY, ColumnZ
FROM inserted
END
GO

Resources