TSQL transform row values into one column table - sql-server

Source Table
Col1 |Col2 |Col3 |Col4 | Col5
----------------------------------
hi | this | is | a | test
Destination Table
RowValues|
----------
hi
this
is
a
test
I am using Dynamic SQL.
Any help ?
This is my code , just change table name and the Id in the where clause to what suits you
DECLARE #sql nVARCHAR(max), #TableName nvarchar(100), #where nvarchar(max)
set #TableName = 'stockItems'
set #where= ' where id = 2'
select #sql ='Select '
select #sql = #sql+ + ' '''+ [name] +' = ''+ cast(' + [name] + ' as nvarchar(10)) as '+[name]+', '
from sys.columns where object_name (object_id) = #TableName
set #sql = stuff(#sql, len(#sql), 1, '') + ' From '+#TableName+ #where
print #sql
set #sql = REPLACE(#sql,', From',' From')
set #sql = #sql + ' '
print #sql
exec(#sql)
Now I need to create a new table that has one column that hold holds each value as a row
Thanks to #Mahmoud-Gamal
The solution should be something like below
declare #cols nvarchar(max)
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(column_name)
FROM information_schema.columns
WHERE table_name = 'vehicles'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
declare #statement nvarchar(max)
set #statement ='
SELECT
ColumnName, Value
FROM
Vehicles
UNPIVOT
(
Value
FOR ColumnName
IN
(
'+#cols+'
)
)
AS A'
execute(#statement)
Please change the "vehicle" table name to any table on your database that has columns from different types (datetime, int and nvarchar) and the below error is shown
Any help ?
The type of column "Description" conflicts with the type of other columns specified in the UNPIVOT list.

Use the UNPIVOT table operator:
SELECT col AS RowValues
FROM table1 AS t
UNPIVOT
(
col
FOR value IN([col1],
[col2],
[col3],
[col4],
[col5])
) AS u;
SQL Fiddle Demo
This will give you:
| ROWVALUES |
|-----------|
| hi |
| this |
| is |
| a |
| test |
Update:
In case you don't know the names of the columns, and you want to do this dynamically, you have to do this using dynamic SQL.
But the problem is how to get the columns names?
You can get the columns names from the information_schema.columns, then concatenate them in one sql, then replace the columns' names in the UNPIVOT with this string, and execute that statement dynamically like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(column_name)
FROM information_schema.columns
WHERE table_name = 'Table1'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = ' SELECT col AS RowValues
FROM table1 AS t
UNPIVOT
(
val
FOR col IN ( ' + #cols + ' )
) AS u;';
EXECUTE(#query);
Updated SQL Fiddle Demo

I believe you want this
Select Col1 + Col2 + Col3 + Col4 + Col5 From Table
Or may be following
Select Col1 From Table1
union Select Col2 From Table1
union Select Col3 From Table1
union Select Col4 From Table1
union Select Col5 From Table1 ;

Related

Use SELECT Result As Column Names

Morning all, Longtime lurker, first time poster.
I'm writing a stored procedure to take the results from one SELECT statement and use that output to build another SELECT statement. Trouble is I can not find a mechanism or code to accomplish this. Assigning the results to a variable doesn't seem to be an option because SQL doesn't support Arrays (that I know of).
+----+-------------+-------------+
| ID | ___$seqval | Column_Name |
+----+-------------+-------------+
| 1 | 0x000000E10 | EnvType |
| 2 | 0x000000E10 | DataType |
| 3 | 0x000000E10 | DateMod |
+----+-------------+-------------+
Trying to get to;
SELECT Column_name(1), Column_name(2)..
From tblServer_Data
There could be up to a total of 20 columns returned.
SQL DEMO
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME([Column_Name])
FROM Table1 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #cols as Columns; -- just for debug
set #query = 'SELECT [ID], ' + #cols + ' from
(
select 1 as ID
, [seqval]
, [Column_Name]
from Table1
) x
pivot
(
max([seqval])
for [Column_Name] in (' + #cols + ')
) p '
SELECT #query as Query; -- just for debug
execute(#query);
OUTPUT
Then you can do SELECT over that output
This will give a SELECT statement of the columns in a selected table.
SELECT 'SELECT ' + STUFF(
(SELECT ',' + c.column_name from
(SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS c
where c.TABLE_NAME = your_table) c
for xml path ('')),1,1,'') + ' FROM ' + your_table

Concatenate dynamically pivoted columns for a variable number of columns

I have been able to successfully pivot different field values into separate columns but what I want is to concatenate all of those separate (pivoted) columns into one column. I don't know how many pivoted columns that I end up with at runtime so I can't just use Column1 + Column2 + Column3 etc.
Here is my sql
--Create a table variable to hold my source data
declare #datatable table
(
OrderId int,
ProductId int,
ClientName varchar(50)
)
--insert some data
insert into #datatable values (1, 2, 'Joe Bloggs')
insert into #datatable values (1, 2, 'Frank Bloggs')
--Create a temp table
--that introduces a new field (called Header)
--to give me column names for my pivoted data
IF OBJECT_ID('tempdb..#PivotedClients') IS NOT NULL DROP TABLE #PivotedClients
create table #PivotedClients
(
OrderId int,
ProductId int,
ClientName varchar(50),
Header varchar(100)
)
insert into #PivotedClients
select OrderId,
ProductId,
ClientName,
'Client ' + Cast(Rank() Over (Partition by OrderId
order by ClientName) as varchar(3))
from #datatable
--Create variables to hold my column names
--and my (dynamic) sql
declare #pivotcolumns nvarchar(max),
#colsWithNoNulls nvarchar(max),
#sqlquery nvarchar(max)
set #pivotcolumns = STUFF(
(
select distinct ',' + QUOTENAME(Header)
from #PivotedClients
for XML PATH (''), TYPE
).value('.', 'nvarchar(max)')
,1,1,'')
set #colsWithNoNulls = STUFF(
(
SELECT DISTINCT ',ISNULL(' + QUOTENAME(Header) + ', '''') ' + QUOTENAME(Header)
FROM #PivotedClients
for XML PATH (''), TYPE
).value('.', 'NVARCHAR(max)')
,1,1,''
)
if OBJECT_ID('tempdb..##Clients ') is not null drop TABLE ##Clients
set #sqlquery = 'select distinct OrderId,
ProductID,
' + #colsWithNoNulls + '
into ##Clients
from
(
select OrderId,
ClientName,
ProductID,
Header
from #PivotedClients) x
pivot
(
Max(ClientName)
for Header in (' + #pivotcolumns + ')
) p'
exec sp_executesql #sqlquery
----
select *
from ##Clients
----
The record set that I currently end up with is:
OrderId ProductId Client1 Client 2
1 2 Frank Bloggs Joe Blogs
What I want is:
OrderID ProductId Clients
1 2 Frank Bloggs Joe Bloggs
I don't know how many 'pivoted' columns that I will end up with at runtime so I can't just use Client1 + Client2 etc
Just need to change your #colsWithNoNulls to perform the string concatenation
set #colsWithNoNulls = STUFF(
(
SELECT DISTINCT '+ '' '' + ISNULL(' + QUOTENAME(Header) + ', '''')'
FROM #PivotedClients
for XML PATH (''), TYPE
).value('.', 'NVARCHAR(max)')
, 1, 1, '') + 'AS Clients'
Also you can do a print #sqlquery before sp_executesql. this will helps you debug your dynamic query

search a string in a table without knowing the column

Note: this is NOT asking
how to select a string where the column name is known.
how to select a string in ALL tables (all google results relate to this one)
This is asking search in only ONE table.
SQL returns error info conversion failed when converting the nvarchar value S3N2V5.
I want to locate the column name where S3N2V5 exists.
No manual methods please. There are 1000000 columns.
Input S3N2V5
Output columnname1ofthistable
Assuming I understand the question, here is one way to get a list of all columns from a single table that contain the search value, using CASE:
Create and populate sample table (Please save us this step in your future questions)
CREATE TABLE T
(
COL1 char(3),
COL2 char(3),
COL3 char(3),
COL4 int
)
INSERT INTO T VALUES
('abc', 'def', 'nop', 1),
('klm', 'nop', 'qrs', 2),
('tuv', 'wzy', 'zab', 3)
Build your dynamic sql:
DECLARE #Search nvarchar(5) = 'nop'
DECLARE #SQL nvarchar(max) = 'SELECT CASE #Search'
SELECT #SQL = #SQL +' WHEN '+ COLUMN_NAME + ' THEN '''+ COLUMN_NAME +''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'T'
AND LOWER(DATA_TYPE) LIKE '%char%' -- only search char, varchar, nchar and nvarchar columns
SELECT #SQL = 'SELECT ColumnName FROM (' +
#SQL + ' END As ColumnName FROM T) x WHERE ColumnName IS NOT NULL'
Execute: (Note that using sp_executeSQL is SQL Injection safe, since we do not concatenate the search parameter into the query, but using it as a parameter)
EXEC sp_executeSQL #SQL, N'#Search nvarchar(5)', #Search
Results:
ColumnName
COL3
COL2
DECLARE #MyValue NVarChar(4000) = 'searchstring';
SELECT S.name SchemaName, T.name TableName
INTO #T
FROM sys.schemas S INNER JOIN
sys.tables T ON S.schema_id = T.schema_id;
WHILE (EXISTS (SELECT * FROM #T)) BEGIN
DECLARE #SQL NVarChar(4000) = 'SELECT * FROM $$TableName WHERE (0 = 1) ';
DECLARE #TableName NVarChar(1000) = (
SELECT TOP 1 SchemaName + '.' + TableName FROM #T
);
SELECT #SQL = REPLACE(#SQL, '$$TableName', #TableName);
DECLARE #Cols NVarChar(4000) = '';
SELECT
#Cols = COALESCE(#Cols + 'OR CONVERT(NVarChar(4000), ', '') + C.name + ') = CONVERT(NVarChar(4000), ''$$MyValue'') '
FROM sys.columns C
WHERE C.object_id = OBJECT_ID(#TableName);
SELECT #Cols = REPLACE(#Cols, '$$MyValue', #MyValue);
SELECT #SQL = #SQL + #Cols;
select substring(#SQL,charindex('.',#SQL)+1,charindex('(',#SQL)-charindex('.',#SQL)-8) as 'TableName'
EXECUTE(#SQL);
DELETE FROM #T
WHERE SchemaName + '.' + TableName = #TableName;
END;
DROP TABLE #T;
This will give you table Name and the entire row from the table which contains the searchstring.
Apart from anwswers mentioned in post : Older Post
1) (using column name) SELECT table_name,table_schema FROM INFORMATION_SCHEMA.COLUMNS WHERE column_name='sort_method';
I hope better you can take dump ( in.sql format ) and you can easily search the content using IDEs like N++.

How do i pivot a table?

I have a dynamic single row Table like:
PersonId|FirstName|LastName|Address|PhoneNumber
-----------------------------------------------
1 Anuj Tamrakar NY +525418
I want to pivot this table and want an output in temp table like:
PersonalDetails|Value
----------------------
PersonId 1
FirstName Anuj
LastName Tamrakar
Address NY
PhoneNumber +525418
The first Table is a dynamic single row temp table. For this example, I have 5 columns. I may have more or less columns depending on my criteria
You actually want to UNPIVOT:
SELECT PersonalDetails, Value
FROM
(SELECT CAST([PersonId] AS VARCHAR(MAX)) AS [PersonId],
CAST([FirstName] AS VARCHAR(MAX)) AS [FirstName],
CAST([LastName] AS VARCHAR(MAX)) AS [LastName],
CAST([Address] AS VARCHAR(MAX)) AS [Address],
CAST([PhoneNumber] AS VARCHAR(MAX)) AS [PhoneNumber]
FROM mytable) p
UNPIVOT
(Value FOR PersonalDetails IN
([PersonId], [FirstName], [LastName], [Address], [PhoneNumber])
) AS unpvt;
All 'to-be-unpivoted' fields have to be of the same type, hence the use of CAST.
Demo here
For a dynamic number of columns you have to use dynamic sql:
DECLARE #cols VARCHAR(MAX) = ''
DECLARE #cast_cols VARCHAR(MAX) = ''
DECLARE #qry VARCHAR(MAX)
SELECT #cols = #cols + ',[' + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'mytable' AND TABLE_SCHEMA='dbo'
SELECT #cast_cols = #cast_cols + ',CAST([' + COLUMN_NAME + '] AS VARCHAR(MAX)) AS [' + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'mytable' AND TABLE_SCHEMA='dbo'
SET #cols = STUFF(#cols, 1, 1, '')
SET #cast_cols = STUFF(#cast_cols, 1, 1, '')
SET #qry = 'SELECT PersonalDetails, Value FROM ('
+ #cast_cols +
'FROM mytable) p
UNPIVOT
(Value FOR PersonalDetails IN (' + #cols + ')
) AS unpvt'
EXEC (#qry)
If you really have a single row in the original table, then you can use a series of UNION operations to get your output:
SELECT 'PersonId' AS PersonalDetails, PersonId AS Value
FROM yourTable
UNION ALL
SELECT 'FirstName' AS PersonalDetails, FirstName AS Value
FROM yourTable
UNION ALL
SELECT 'LastName' AS PersonalDetails, LastName AS Value
FROM yourTable
UNION ALL
SELECT 'Address' AS PersonalDetails, Address AS Value
FROM yourTable
UNION ALL
SELECT 'PhoneNumber' AS PersonalDetails, PhoneNumber AS Value
FROM yourTable
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('dbo.yourTableName')
This gives you your column names. You simply insert the column names in your new table and use ``, insert into temp(PersonalDetails, Value) values(column1,select column1 from SingleRowTable

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