T-SQL Pivot Sort Order - sql

I have a table that has contact information ordered by sort order and then going down in the column.
Contacts Table:
I need to create a table where the emergency contact infomration is sorted by Columns instead of rows:
How can I do this?

Your dyanmic pivot query should be like in this demo
declare #cols nvarchar(max);
declare #query nvarchar(max);
select
sourceId,
patientId,
data,
cols= concat(col,sortOrder)
into #t
from
Contacts
UNPIVOT
(
data for col in
(
personalContactType_MisContactTypeId,
personalContactNameLast,
personalContactNameFirst
)
)up
select #cols= stuff((
select distinct ','+ quotename(cols)
from #t
for xml path('')),1,1,'')
select #cols
select #query= 'select * from #t
pivot
( max(data) for cols in ('+#cols+
'))p'
exec (#query)

In your dynamic pivot, use SortOrder to ORDER BY when creating your column list.

Related

Display data in specific format using SQL query

I have data in current format
and I want to get data through SQL query in
Can some one explain what should I search or how can I write SQL query with this. I'm not an expert in SQL.
You need dynamic pivot query to achieve this. try below query
declare #columns varchar(max)='',#sql nvarchar(max);
Create table #temp (Name nvarchar(max));
insert into #temp select distinct date from YourTable --inert distinct date for pivot column
SELECT #columns+=QUOTENAME(Name) + ',' from #temp
SET #columns = LEFT(#columns, LEN(#columns) - 1);
set #sql='
SELECT * FROM
(
select ID,cast(Status as int) Status,date from YourTable
) t
PIVOT(Max(Status)
FOR date IN ('+#columns+')
) AS pivot_table
'
EXEC (#Sql)
Drop Table #temp

Query written to pull rows into columns without aggregation is jumbling the columns rather than listing them in order

TL;DR: Around 1800 functions are turned into columns for "pivot" but they are not being called in order, such that function_376 is consistently called first then "random" others and not all roles have that many functions and it's pulling nulls. How do I get it to pull the functions in order?
I am trying to create a query to produce a result set that can be easily copy and pasted into Excel in a human readable fashion. The normal result set from my query pulls two columns, role and function, with a row for each distinct pair. My objective is to pull the functions all onto the same line and have a column for each function assigned to the role. The closest I have gotten is to repurpose a script I found in this answer but the problem I am running into is that the query to return the results is jumbling the columns. It is not returning them in the order row, function1,function2, etc. and as result is pocked with NULLs which is making the output virtually useless. The #cols query is pulling the functions together in a consistent order every time I run it but it is not in numerical order, it appears random. Each Function_N column represents the Nth function associated with the role so if I could get the #cols query to build in order, then this would work.
How can I rewrite this so that the output will have the functions listed in numerical order such that the results are left justified?
Code and screenshot of results shown below.
IF OBJECT_ID('tempdb.dbo.#roles', 'U') IS NOT NULL
DROP TABLE #roles;
CREATE TABLE #roles([role] VARCHAR(MAX), [function] VARCHAR(MAX))
Insert into #roles
select distinct r.r_desc, f.f_desc
from roles r
join role_functions rf on rf_rid = r_id
join Functions f on f_id = rf_fid
where r.r_Active = 'y'
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ','
+ QUOTENAME(rn)
from
(
select 'function_'+cast(row_number() over(partition by [role]
order by [role]) as varchar(20)) rn
from #roles
) src
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [Role],' + #cols + ' from
(
select [Role], [function],
''function_''+cast(row_number() over(partition by [role]
order by [role]) as varchar(20)) rn
from #roles
) x
pivot
(
max([function])
for rn in (' + #cols + ')
) p '
execute(#query)
Image of results
I solved it! The distinct was a nod in the right direction. I also needed another temp table for calculating the max column count and then I used a variable to pass that into the first stuff function. See below:
IF OBJECT_ID('tempdb.dbo.#roles', 'U') IS NOT NULL
DROP TABLE #roles;
IF OBJECT_ID('tempdb.dbo.#funtcnt', 'U') IS NOT NULL
DROP TABLE #funtcnt;
CREATE TABLE #roles([role] VARCHAR(MAX), [function] VARCHAR(MAX))
Insert into #roles
select distinct r.r_desc, f.f_desc
from roles r
join role_functions rf on rf_rid = r_id
join Functions sf on f_id = rf_fid
where r.r_Active = 'y'
select [role], count([function]) as [count]
INTO #funtcnt
from #roles group by [role]
declare #topcount varchar(max) = (select top 1 [role] from #funtcnt order by [count] desc)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ','
+ QUOTENAME(rn)
from
(
select 'function_'+cast(row_number() over(partition by [role]
order by [role]) as varchar(20)) rn
from #roles where [role] = #topcount
) src
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [Role],' + #cols + ' from
(
select [Role], [function],
''function_''+cast(row_number() over(partition by [role]
order by [role]) as varchar(20)) rn
from #roles
) x
pivot
(
max([function])
for rn in (' + #cols + ')
) p '
execute(#query)

SQL Pivot Table from dynamic columns

I wrote this query to generate pivot table :
SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN (select ItemName_AR from WH_Items)
)AS pvt
but it cuases the following error in
Incorrect syntax near the keyword 'select'.
at this statment
FOR [ItemName] IN (select ItemName_AR from WH_Items)
Unfortunately, you may not use a select statement to provide the variety of values (unpivoted form)=columns(pivoted form). You may either use
IN ([value1],[value2]) etc
or consider a dynamic solution, here's a link:
SQL Server Dynamic Pivot Column Names
You cannot create Dynamic SQL PIVOT like that. You may try something like this...
DECLARE #cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ',' + Quotename(ItemName_AR)
FROM WH_Items
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE #query AS NVARCHAR(max) = 'SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN ('+ #cols +')
)AS pvt';
EXECUTE(#query)

How to Un Pivot the Table With Date Headers in Sql

I have the following Temp table with Date Header How to UnPivot this Table
I need Like This type result
Here is the solution to your Problem:
DECLARE #colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsUnpivot
= stuff((select ','+quotename(C.name)
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('table')
for xml path('')), 1, 1, '')
set #query
= 'select sno,EmpId, Name, Date, Value
from table
unpivot
(
Date
FOR EmpId IN ('+ #colsunpivot +')
) u'
exec sp_executesql #query;
I used dynamic query since if you don't know how much columns are there in your table.
You can also use below static query :
SELECT sno, EmpId, Name, Date, Value
FROM
(SELECT *
FROM table) p
UNPIVOT
(Date FOR EmpId IN
(01-Mar-18,02-Mar-18,03-Mar-18,04-Mar-18,05-Mar-18)
)AS unpvt;
try the following script:
SELECT [s#no], [Emp#ID], [Name], [Date], [Shiftid]
FROM
(SELECT * FROM table_name) SRC
UNPIVOT
([Date] FOR [Emp#ID]
IN ([01-Mar-18], [02-Mar-18], [03-Mar-18], [04-Mar-18], [05-Mar-18])
) UNPVT;

Moving Column names to rows

I have such a table with date as column name
but I would like to have these dates in one column in more than one row something like this:
Date Index
20170806 9206
20170813 8041
20170820 8861
20170827 8356
How can I do it in SQL Server
If you would like to go for more dynamic solution rather than hard coding all columns, the below scripts should work:
IF OBJECT_ID('TestTable') IS NOT NULL
DROP TABLE TestTable;
CREATE TABLE TestTable
(
[20170806] INT NOT NULL,
[20170813] INT NOT NULL,
[20170820] INT NOT NULL,
[20170827] INT NOT NULL
)
INSERT INTO TestTable VALUES (9206, 8041, 8861, 8356)
DECLARE #cols NVARCHAR(MAX),
#sql NVARCHAR(MAX)
SELECT #cols = COALESCE(#cols + ',', '') + QUOTENAME(c.COLUMN_NAME)
FROM INFORMATION_SCHEMA.[COLUMNS] AS c
WHERE c.TABLE_NAME = 'TestTable'
SET #sql = '
SELECT [Date],
[Index]
FROM TestTable
UNPIVOT([Index] FOR [Date] IN ('+ #cols +')) AS up'
exec sp_executesql #sql;
You can use UNPIVOT for this.
SELECT * FROM MyTable
UNPIVOT([Date] For [Index] IN( [20170806], [20170813], [20170820], [20170827])) UNPVT
In addition, if you want to make it dynamically, you can use this query too.
DECLARE #ColNames NVARCHAR(MAX)
= STUFF(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
(SELECT T.* FROM (VALUES(1)) AS DUMY(ID) LEFT JOIN MyTable T ON 1=2 FOR XML AUTO, ELEMENTS XSINIL )
,'<T xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">','')
,'</T>','')
,'_x0032_','2')
,' xsi:nil="true"/>','] ')
,'<',',[') ,1,1,'')
DECLARE #SqlQ NVARCHAR(MAX)
= 'SELECT * FROM MyTable UNPIVOT([Date] For [Index] IN( ' + #ColNames + ')) UNPVT'
EXEC sp_executesql #SqlQ
You could use pivot such as:
However, i dont know your exact table names
select field_names
from table_name
pivot
( index
for index in ( Date, Index)
) pivot
but a useful article to follow is
"https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx"
Designed the table (variable) structure as below.
Hopefully, it matches your table structure.
DECLARE #data TABLE
(
[20170806] INT,
[20170813] INT,
[20170820] INT,
[20170827] INT
)
INSERT INTO #data VALUES (9206, 8041, 8861, 8356)
SELECT * FROM #data
You can use UNPIVOT statement for this. If you have dynamic columns, check this.
SELECT [Date],[Index]
FROM
#data
UNPIVOT
(
[Index] FOR [Date] IN ([20170806], [20170813], [20170820], [20170827])
) AS unpivotTable;
and the output is