Change row value to column in SQL - sql

I have table in sql i want to change fieldColumnName as a column and fieldValue as a row.
this is my table image

As per your question, You want to alter table (change column name as well as data type)
ALTER TABLE tablename
CHANGE `fieldColumnName` `column` VARCHAR(255),
CHANGE `fieldValue` `row` VARCHAR(255)
In above query you change datatype as you wish.

If you know all the possible values in the fieldColumnName column then you could use pivot like this:
declare #data table(fieldValue varchar(50), fieldColumnName varchar(50))
INSERT INTO #data
SELECT '1 - value', 'col1'
UNION
SELECT '2 - value', 'col2'
UNION
SELECT NULL, 'col6'
select *
from #data
select col1, col2, col3
from
(
select fieldValue, fieldColumnName
from #data
) d
pivot
(
max(fieldValue)
for fieldColumnName in (col1, col2, col3)
) piv;

Related

How to write a SQL query for the below?

I have two tables with n of columns from Col1 to Col30
Table 1.
Templateid Col1 Col2 Col3 Col4 ...
95 2019-05-28 1234 test123 123456
Table 2.
Templateid DisplayName ColumnName
95 date col1
95 rank col2
95 purpose col3
95 sign col4
Expected Results.
Col1Name Col1Value Col2Name Col2Value Col3Name Col3Value ....
date 2019-05-28 rank 1234 purpose test123
This is a crude way of doing it and if you do not know the number of columns in each table you would need to use dynamic sql to enumerate them out but for the purposes of this example I have assumed you do know the number of columns and the names you want to populate.
The union query allows you to pre-populate the desired column names using the col1 syntax, then the pivot allows you to match up the displaynames and the display values. A case statement is required to ensure the correct values are shown and you do need to populate your derived column names for the pivot query but you do get the desired outcome this way.
declare #table1 table (
Templateid int,
Col1 date,
col2 int,
col3 nvarchar(10),
col4 int
);
insert into #table1 (Templateid, col1, col2, col3, col4)
values
(95, '2019-05-28', '1234', 'test123', '123456');
declare #table2 table (
Templateid int,
Displayname nvarchar(10),
ColumnName nvarchar(10)
);
insert into #table2 (Templateid, Displayname, ColumnName)
values
(95, 'date', 'col1'),
(95, 'rank', 'col2'),
(95, 'purpose', 'col3'),
(95, 'sign', 'col4');
select * from
(
select columnname+'Name' as columnname, Displayname
from #table2 t2
union
select columnname+'Value', case when columnname='col1' then cast(col1 as nvarchar(15))
when columnname='col2' then cast(col2 as nvarchar(15))
when columnname='col3' then cast(col3 as nvarchar(15))
when columnname='col4' then cast(col4 as nvarchar(15)) end
from #table1 t1 inner join #table2 t2 on t1.Templateid=t2.Templateid) src
pivot
(max(displayname) for columnname in ([col1Name],[col1Value], [col2Name],[col2Value], [col3Name],[col3Value], [col4Name],[col4Value])) piv;

Select rows with same data in columns

I have a SQL Server database with a table with 20 columns. These columns have data as agree or disagree. Now I want to show rows in these columns which have "agree" data in them. I can use where clause but it is a time consuming task for 20 columns. I am looking for a SQL query which does this task.
You can use in:
select t.*
from t
where 'agree' in (col1, col2, ... col20);
There is no shortcut for this type of scenarios, If you want to compare all the columns, you have to explicitly mention each and every column like .
WHERE Col1='agree' AND Col2="agree"....
To avoid coding, you may go with dynamic query creation or creating a function, but ultimately it will be executed as same query comparing all the columns.
What about JOIN ?
If u have such a complex logic, best practices advise to keep data in different tables.
Here's some simplified example code that tests out several methods to return records that may or may not agree.
Just for the fun of it actually.
declare #T table (id int identity(1,1) primary key, col1 varchar(30), col2 varchar(30), col3 varchar(30));
insert into #T (col1, col2, col3) values
('agree','agree','agree'),
('agree','disagree','disagree'),
('agree','disagree',null),
('disagree','disagree','disagree'),
('disagree','disagree',null),
(null,null,null);
select 'OR' as method, * from #T
where (col1='agree' OR col2='agree' OR col3='agree');
select 'AND' as method, * from #T
where (col1='agree' AND col2='agree' AND col3='agree');
select 'IN' as method, * from #T
where 'agree' IN (col1, col2, col3);
select 'NOT IN' as method, * from #T
where 'agree' NOT IN (col1, col2, col3);
select 'LIKE' as method, * from #T
where CONCAT('-',col1,'-',col2,'-',col3,'-') LIKE '%-agree-%';
select 'NOT LIKE' as method, * from #T
where CONCAT('-',col1,'-',col2,'-',col3,'-') NOT LIKE '%-agree-%';
select 'ALL' as method, * from #T
where 'agree' = ALL(select col from (values (col1),(col2),(col3))q(col));
select 'SOME' as method, * from #T
where 'agree' = SOME(select col from (values (col1),(col2),(col3))q(col));
select 'ANY' as method, * from #T
where 'agree' = ANY(select col from (values (col1),(col2),(col3))q(col));
select 'EXISTS' as method, * from #T
where EXISTS (
select 1
from (values (col1),(col2),(col3))q(col)
where col = 'agree'
);
select 'NOT EXISTS' as method, * from #T
where NOT EXISTS (
select 1
from (values (col1),(col2),(col3))q(col)
where col = 'agree'
);

Convert each column of a record into separate record

I have a record:
DECLARE #Tbl AS TABLE(Col1 VARCHAR(10), Col2 VARCHAR(10), Col3 VARCHAR(10));
INSERT INTO #Tbl
VALUES('Val1', 'Val2', 'Val3')
-- Source Record
SELECT Col1, Col2, Col3 FROM #Tbl
Result: Val1 Val2 Val3
I want result of each column as separate two column records like first column will become the title of source column and second column should be the value of source column like the result of below query in which I have achieved the result by UNION ALL :
--Query for Target Result
SELECT 'Col1' AttributeTitle, CONVERT(VARCHAR, Col1) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col2' AttributeTitle, CONVERT(VARCHAR, Col2) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col3' AttributeTitle, CONVERT(VARCHAR, Col3) AttributeValue FROM #Tbl
Problem in this query is I have to explicitly define the columns, is there any way that it should dynamically get the columns names and their values?
You could use UNPIVOT but you still need to know the names of the columns.
SELECT ColumnName, ValueName
FROM (SELECT * FROM #Tbl) AS Data
UNPIVOT
( ValueName
FOR ColumnName IN (Col1, Col2, Col3)
) AS PivottedOutput
I like the apply method for unpivoting in SQL Server:
select v.*
from #tbl t cross apply
(values ('col1', col1),
('col2', col2),
('col3', col3)
) v(AttributeTitle, AttributeValue);
This simplifies the query but it does not directly answer the question.
If you want a variable number of columns, then you are going to have to use dynamic SQL. This is a bit cumbersome on a real table. However, with a table variable or a temporary table, you have the additional issue of scoping rules -- the name of the table will not be in scope when you execute the statement.

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;