Pivoting the table and show column as rows - sql

I have a table, I want to pivot the table, my desired output is #tab2.
My table is as follows:
declare #tab1 table(name varchar(50),mobile varchar(10),address varchar(100))
insert into #tab1 values('Test','2612354598','CG-10')
select * from #tab1
My desired output is:
declare #tab2 table(colname varchar(50),value varchar(100))
insert into #tab2 values('name','Test'),('mobile','2612354598'),('address','CG-10')
select * from #tab2
Please help

what are you looking is Unpivot not Pivot. Use Unpivot as follows. make sure that all columns have same datatype.
select
colname,
value
from #tab1
unpivot
(
value
for colname in ([name]
,[mobile]
,[address]
)
) unpiv;

If using SQL server you can use UNPIVOT.
SELECT colname, valueid
FROM
(SELECT CAST(name as varchar(100)) name, CAST(mobile as varchar(100))
mobile, address FROM #tab1) p
UNPIVOT
(valueid FOR colname IN
(name,mobile, address)
)AS unpvt;
You need to CAST() the columns so the type is the same for all of them.

Related

String split ,sort and compare with another column within a table SQL

Create Table #temp
(
Change varchar(20),
deleted_user_id int,
deleted_field_id int,
deleted_value nvarchar (4000),
inserted_user_id int,
inserted_field_id int,
inserted_value nvarchar (4000),
is_difference int,
)
insert into #temp values ('UPDATE','1', '11', '3,2,1,4','1','11','1,2,3,4','0')
insert into #temp values ('UPDATE','1', '12', '','1','12','1,2,3','0')
insert into #temp values ('UPDATE','2', '12', '1,2','2','12','','0')
select * from #temp
I am using Microsoft SQL server management studio
I am trying to compare the deleted value with inserted value. if there is a difference then set is_difference column to 1 or just return the rows.
so far I am thinking to do string split. maybe use stuff function. but not quite sure how to use all these to in a single query or is there any other option. Any help is appreciated. Thanks in advance
this query works so far.
;with cte as
(select isnull(deleted_user_id, inserted_user_id) as user_id,
isnull(deleted_field_id, inserted_field_id) as field_id,
stuff(
(
SELECT ','+ value FROM STRING_SPLIT (deleted_value, ',') group by value order by value FOR XML PATH('')
),1,1,'') as sorted_deleted_value , inserted_value
from #temp )
select * from cte where sorted_deleted_value <> inserted_value

How to select from string array added in SQL column?

Below is my table,
create table t(
id int,
colParam varchar(max))
insert into t values(1,'["param1", "param2"]')
insert into t values(2,'["param2"]')
insert into t values(3,'["param1"]')
insert into t values(4,'["param2", "param3"]')
insert into t values(5,'["param1", "param2"]')
tried
declare #str varchar(max) = 'param1'; Select * from t where colParam like '%'+ #str+'%'
its not working for
declare #str varchar(max) = 'param1,param2'; Select * from t where colParam like '%'+ #str+'%'
i want to select rows by passing colPar as 'param1,param2' so it will result me all the records containing param1 and param2 in colParam
This quiet tricky.
create table #t(
id int,
colParam varchar(max)
)
insert into #t values(1,'["param1", "param2"]')
insert into #t values(2,'["param2"]')
insert into #t values(3,'["param1"]')
insert into #t values(4,'["param2", "param3"]')
insert into #t values(5,'["param1", "param2"]')
declare #str varchar(max) = 'param1,param2';
to Return all matching values.
select distinct id, t1.colParam from #t t1
cross apply string_split(t1.colParam, ',') t2
cross apply string_split(#str, ',') t3
where t2.value like '%'+t3.value+'%'
Output:
If you are using SQL Server 2016 and above, then you can use STRING_SPLIT.
As MSDN says:
A table-valued function that splits a string into rows of substrings,
based on a specified separator character.
So your can look like this:
DECLARE #t TABLE
(
id int,
colParam varchar(max)
)
insert into #t values(1,'["param1", "param2"]')
insert into #t values(2,'["param2"]')
insert into #t values(3,'["param1"]')
insert into #t values(4,'["param2", "param3"]')
insert into #t values(5,'["param1", "param2"]')
SELECT
t.id
, s.col
FROM #t AS t
OUTER APPLY
(
SELECT
spl.value AS col
FROM STRING_SPLIT(
(SELECT _t.colParam FROM #t AS _t WHERE _t.id = t.id), ',') AS spl
)s

SQL Server stored procedure store 2 table variable in 1 table with from and to values

I have this table stored in variable #oldValues and #newValues:
The two tables above will contain 1 row maximum. My goal is to insert this to a new table JSON TABLE:
DECLARE #jsonTable TABLE
(
[Field] nvarchar(max),
[From] nvarchar(max),
[To] nvarchar(max)
);
and store the from to values from old and new variable
Output must be like this:
[Field] [From] [To] // this is a column name
------------------------------------
CommitteeID 1 1
CommitteeName Test Test2
CommitteeMemberID 1 3
How can I achieve that?
Thanks in advance
It can be plain
select 'CommitteeId' [Field], (select cast(CommitteeId as varchar(max)) from #oldValues) [From], (select cast(CommitteeId as varchar(max)) from #newValues)[To]
union all
select 'CommitteeName', (select CommitteeName from #oldValues), (select CommitteeName from #newValues)
union all
select 'CommitteeId', (select cast(CommitteeMemberId as varchar(max)) from #oldValues), (select cast(CommitteeMemberId as varchar(max)) from #newValues)
If you have only one row:
select v.*
from #oldValues ov cross join
#newValues nv outer apply
(values ('CommitteeId', ov.CommitteeId, nv.CommitteeId),
('CommitteeName', ov.CommitteeName, nv.CommitteeName),
('CommitteeMemberID', ov.CommitteeMemberID, nv.CommitteeMemberID)
) v(field, [from], [to]);
Note: This assumes that the types for the values are all compatible. Otherwise, you may need to convert/cast values to strings.
EDIT:
To be explicit, the casts are:
select v.*
from #oldValues ov cross join
#newValues nv outer apply
(values ('CommitteeId', cast(ov.CommitteeId as nvarchar(255)), cast(nv.CommitteeId as nvarchar(255))),
('CommitteeName', cast(ov.CommitteeName as nvarchar(255)), cast(nv.CommitteeName as nvarchar(255))),
('CommitteeMemberID', cast(ov.CommitteeMemberID as nvarchar(255)), cast(nv.CommitteeMemberID as nvarchar(255)))
) v(field, [from], [to]);
I think UNPIVOT operator most proper solution for the need.
For UNPIVOT operation all column types should be same, that's why we cast all column type to the same.
DECLARE #oldValues as TABLE (CommitteeID INT, CommitteeName VARCHAR(20), CommitteeMemberID INT)
INSERT INTO #oldValues VALUES (1,'Test',1)
DECLARE #newValues as TABLE (CommitteeID INT, CommitteeName VARCHAR(20), CommitteeMemberID INT)
INSERT INTO #newValues VALUES (1,'Test2',3)
DECLARE #jsonTable TABLE
(
[Field] nvarchar(max),
[From] nvarchar(max),
[To] nvarchar(max)
);
;WITH FromTable AS (
SELECT [Field] , [From]
FROM (SELECT CAST(CommitteeID AS VARCHAR(255)) CommitteeID,
CAST(CommitteeName AS VARCHAR(255)) CommitteeName,
CAST(CommitteeMemberID AS VARCHAR(255)) CommitteeMemberID
FROM #oldValues) p
UNPIVOT ( [From] FOR [Field]
IN ( CommitteeID , CommitteeName , CommitteeMemberID)) as UNPVT
)
, ToTable AS (
SELECT [Field] , [To]
FROM (SELECT CAST(CommitteeID AS VARCHAR(255)) CommitteeID,
CAST(CommitteeName AS VARCHAR(255)) CommitteeName,
CAST(CommitteeMemberID AS VARCHAR(255)) CommitteeMemberID
FROM #newValues) p
UNPIVOT ( [To] FOR [Field]
IN ( CommitteeID , CommitteeName , CommitteeMemberID)) as UNPVT
)
SELECT F.*, T.[To] FROM FromTable F FULL JOIN ToTable T ON F.[Field] = T.[Field]
New columns can be easily added to SELECT and IN part of the query.
For easily determine missing column I used FULL JOIN

How can I get around differences in column types when using unpivot?

I am having problems using unpivot on columns, that are not the exact same datatype, and I can't figure out how to convert the columns on the fly, because the syntax for UNPIVOT does not seem to support it.
Consider this example:
DECLARE #People TABLE
(PersonId int, Firstname varchar(50), Lastname varchar(50))
-- Load Sample Data
INSERT INTO #People VALUES (1, 'Abe', 'Albertson')
INSERT INTO #People VALUES (2, 'Benny', 'Boomboom')
SELECT PersonId, ColumnName, Value FROM #People
UNPIVOT
(
ColumnName FOR
Value IN (FirstName, LastName)
)
The result would be this:
PersonId ColumnName Value
----------- ----------------- ----------------
1 Abe Firstname
1 Albertson Lastname
2 Benny Firstname
2 Boomboom Lastname
Everything is unicorns and rainbows. Now I change the datatype of Lastname to varchar(25) and everything breaks. The output is:
The type of column "Lastname" conflicts with the type of other columns
specified in the UNPIVOT list.
How can I get around this and convert everything to say a varchar(50) on the fly, without tampering with the actual data types on the table?
SqlFiddle working example (same datatype): http://sqlfiddle.com/#!3/f3719
SqlFiddle broken example (diff datatypes): http://sqlfiddle.com/#!3/5dca13/1
You cannot convert inside the UNPIVOT syntax but you can convert the data inside a subquery similar to the following:
select PersonId, ColumnName, Value
from
(
select personid,
firstname,
cast(lastname as varchar(50)) lastname
from People
) d
unpivot
(
Value FOR
ColumnName in (FirstName, LastName)
) unpiv;
See SQL Fiddle with Demo
Another way to do this would be to use CROSS APPLY, depending on your version of SQL Server you can use CROSS APPLY with VALUES or UNION ALL:
select PersonId, ColumnName, Value
from People
cross apply
(
select 'firstname', firstname union all
select 'lastname', cast(lastname as varchar(50))
) c (ColumnName, value)
See SQL Fiddle with Demo.
select col1, col2, Answer, Question_Col
from (
SELECT
col1,
col2,
col3,
CAST(col4 AS NVARCHAR(MAX)) col4,
-- Note: Here datatype should be same as that of previous columns
CAST(col5 AS NVARCHAR(MAX)) col5
FROM Table_Name )a
unpivot
(
Answer
for Question_Col in (
col3,
col4,
col5
)
) unpiv;

How to convert a column header and its value into row in sql?

I have a table with columns say col1, col2, col3. The table has many rows in it.
Let's assume val1, val2, val3 is one such row. I want to get the result as
Col1, Val1
Col2, Val2
Col3, Val3
That is 3 rows - one for each column and its value.
I am using SQL Server 2008. I read about pivots. Are pivots a way to solve this problem? Can someone route me to some examples or solutions how to solve this problem?
Thanks a lot
Maybe something like this:
Test data
DECLARE #T TABLE(Col1 INT, Col2 INT, Col3 INT)
INSERT INTO #T
VALUES (1,1,1)
Query
SELECT
*
FROM
(
SELECT
t.Col1,
t.Col2,
t.Col3
FROM
#T AS t
) AS SourceTable
UNPIVOT
(
Value FOR Col IN
(Col1,Col2,Col3)
) AS unpvt
Output
1 Col1
1 Col2
1 Col3
To do this kind of thing read the following: Using PIVOT and UNPIVOT
Pivot function allow you to convert row values in from of column..
Also check : Dynamic Pivoting in SQL Server
Example :
create table #temptable(colorname varchar(25),Hexa varchar(7),rgb varchar(1), rgbvalue tinyint)
GO
insert into #temptable values('Violet','#8B00FF','r',139);
insert into #temptable values('Violet','#8B00FF','g',0);
insert into #temptable values('Violet','#8B00FF','b',255);
insert into #temptable values('Indigo','#4B0082','r',75);
insert into #temptable values('Indigo','#4B0082','g',0);
insert into #temptable values('Indigo','#4B0082','b',130);
insert into #temptable values('Blue','#0000FF','r',0);
insert into #temptable values('Blue','#0000FF','g',0);
insert into #temptable values('Blue','#0000FF','b',255);
SELECT colorname,hexa,[r], [g], [b]
FROM
(SELECT colorname,hexa,rgb,rgbvalue
FROM #temptable) AS TableToBePivoted
PIVOT
(
sum(rgbvalue)
FOR rgb IN ([r], [g], [b])
) AS PivotedTable;
Create a temproary table:
CREATE TABLE #table2
(
name NCHAR,
bonus INT
)
Now Select and execute the below statement if there is an empty.
SELECT * FROM #table2
INSERT INTO #table2 (name,bonus) VALUES ('A',10)
INSERT INTO #table2 (name,bonus) VALUES ('B',20)
INSERT INTO #table2 (name,bonus) VALUES ('C',30)
After insert the values into table. select and execute the below line if you get records:
SELECT * FROM #table2
Input:
name bonus
A 10
B 20
C 30
Change the input into like this result
Result:
Cost A B C
Bonus 10 20 30
By using this code:
SELECT 'Bonus' AS Cost,
[A],[B],[C]
FROM
(SELECT name, Bonus
FROM #table2) AS TempTbl
PIVOT
(
AVG(bonus)
FOR [name] IN ([A],[B],[C])
) AS PivotTable;