Convert sql Rows into Column using Pivot as shown below - sql

I am looking to generate a report which is basically a attendance report using SQL query from table data rows; I have employee punch data as row in table with columns such as
PDate | EmpCode | EmpName | PStatus | OT
enter image description here
The above image shows the snap of data in table.
I am looking to generate the results as shown below
enter image description here

SELECT * FROM ( SELECT [Name], [Value] FROM [dbo].[Table] ) AS SourceTable PIVOT ( MAX([Value]) FOR [Name] IN ( [FirstName], [LastName], [Email], [Phone] ) ) AS PivotTable
it will help you

Related

I need to unpivot columns to rows where pairs of columns stay together in the results

The following article comes close, but I can't make the leap to my need: Unpivot pairs of associated columns to rows
IF OBJECT_ID ('dbo.tst_CrossApply') IS NOT NULL
DROP TABLE dbo.tst_CrossApply;
create table dbo.tst_CrossApply
(
GivenDay varchar(32) null,
OtherData varchar(32) null,
CODRPL varchar(32) null,
COD varchar (32) null,
BODRPL varchar(32) null,
BOD varchar (32) null,
)
go
insert into dbo.tst_CrossApply values ( 'Day1','OtherData1','<', '5','', '10')
insert into dbo.tst_CrossApply values ( 'Day2','OtherData2', '', '20','<', '30')
go
SELECT * FROM dbo.tst_CrossApply
SELECT t.[GivenDay],t.[OtherData],v.[RPL],v.[Result]
FROM [dbo].[tst_CrossApply] t
CROSS APPLY (VALUES ([CODRPL], [COD]),([BODRPL], [BOD])) v ([RPL],[Result])
The above script returns the above with the second piture minus the needed Column 'Parameter'.
I can get this column, but not the pairing of the RPL and Result columns using UNPIVOT
In my database there are several 'OtherData' columns, and several pairs of columns to CrossApply and/or UNPIVOT.
The following includes the Parameter column I need, which is one of the second of the paried column headings.
Any help is appreciated.
You're close. See the "Unpivoting" example linked in the next thread.
SELECT t.[GivenDay]
, t.[OtherData]
, v.[Param]
, v.[RPL]
, v.[Result]
FROM [dbo].[tst_CrossApply] t
CROSS APPLY (
VALUES ('COD', [CODRPL], [COD])
, ('BOD', [BODRPL], [BOD])
) v ([Param], [RPL],[Result])
Update 2022-03-02
I'm not aware of a simple alternative using UNPIVOT. The closest I could get was more convoluted than just using CROSS APPLY
SELECT cod.GivenDay, cod.OtherData, cod.Param, cod.RPL, cod.Result
FROM (
SELECT GivenDay, OtherData, COD, CODRPL AS RPL
FROM [dbo].[tst_CrossApply] t
) pvt
UNPIVOT
(
Result FOR Param IN (COD)
) AS cod
UNION ALL
SELECT bod.GivenDay, bod.OtherData, bod.Param, bod.RPL, bod.Result
FROM (
SELECT GivenDay, OtherData, BOD, BODRPL AS RPL
FROM [dbo].[tst_CrossApply] t
) pvt
UNPIVOT
(
Result FOR Param IN (BOD)
) AS bod
ORDER BY GivenDay, OtherData, Param
db<>fiddle here

Pivot employee table in SQL Server?

I have written the query to get the first result in SQL Server.
And I want to pivot this table into the following format. I need help pivoting this table in SQL Server.
You can go for simple PIVOT as given below:
DECLARE #table table(division varchar(30), emp int, month varchar(30))
INSERT INTO #table
values
('AAA',50,'December')
,('BBB',100,'December')
,('AAA',200,'January')
,('BBB',150,'January')
,('AAA',60,'February')
,('BBB',70,'February ')
SELECT * FROM #table
pivot (sum(emp) for month in ([December],[January],[February])) as pvt
division
December
January
February
AAA
50
200
60
BBB
100
150
70
If you want to Pivot a table in sql server here is how you do it
select [Division],[December],[January],[February]
from(
select * from SOF
) tbl
pivot(
Min(Emp) for Month in ([December],[January],[February])
) pvt
This query will get your results according to provided data. This is how PIVOT works.
select
<non pivot column 1>,
<non pivot column 2>,
<pivoted column 1>,
<pivoted column 2>,
............
from (
--Result from the query
select * from yourTable
) tbl
pivot(
<Aggregation function> For [<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
)

Improve SQL Query to find redundant data

the following shows my sample dataset
PatientID PatientName
XXX-037070002 Riger, Jens^Wicki
XXX-037070002 Riger^Wicki
XXX-10052 Weier,Nicole^Peggy
XXX-10052 Weier,Nicole^Peppy
XXX-23310 Rodem^Sieglinde
XXX-23310 Sauberger, Birgit^Finja
XXX-23343 Je, Ronny^Wilma
XXX-23343 Jer, Ronny^Wilma
XXX-2349 Kel,Andy^Juka
XXX-2349 Kel^Juka
XXX-2998 Hel, Frank
XXX-2998 Hel,Frank^Fenris
XXX-3188 Mey, Marion
XXX-3188 Mey, Marion^Paula
XXX-3188 Schulz^Roma
XXX-3218 Böntgen-Simnet,Dr. Regine^Cara
XXX-3218 Simnet,Dr. Regine^Cara
XXX-3826 Mertes, Bernd Uwe^Ellie
XXX-3826 Mertes,Bernd^Ellie
XXX-3826 Mertes^Ellie
This is the query I got from my last request:
with d as
(
select distinct
patid,
patname
from dicomstudys
)
select *
from d
where d.patid in
(
select d.patid
from d
group by d.patid
having count(*) > 1
)
Now I want to adjust the query that only the following data get's an output:
PatientID PatientName
XXX-23310 Rodem^Sieglinde
XXX-23310 Sauberger, Birgit^Finja
XXX-23343 Je, Ronny^Wilma
XXX-23343 Jer, Ronny^Wilma
XXX-3188 Mey, Marion
XXX-3188 Mey, Marion^Paula
XXX-3188 Schulz^Roma
XXX-3218 Böntgen-Simnet,Dr. Regine^Cara
XXX-3218 Simnet,Dr. Regine^Cara
Last names are either seperated with a ',' or '^' . If last names are the same for the same PatientID then I dont want them being displayed. I tried fiddling with a sub select statement featuring a combination of CHARINDEX commands and others but my SQL syntax knowledge is very limited with the complexity of the request.
Please also note that for the case for XXX-3188 has two datasets with the same last name but also another dataset with a complete new patientName and thus it needs to be in the output.
Try this:
DECLARE #DataSource TABLE
(
[ID] VARCHAR(32)
,[Name] VARCHAR(256)
);
INSERT INTO #DataSource ([ID], [Name])
VALUES ('XXX-037070002', 'Riger, Jens^Wicki')
,('XXX-037070002', 'Riger^Wicki')
,('XXX-10052', 'Weier,Nicole^Peggy')
,('XXX-10052', 'Weier,Nicole^Peppy')
,('XXX-23310', 'Rodem^Sieglinde')
,('XXX-23310', 'Sauberger, Birgit^Finja')
,('XXX-23343', 'Je, Ronny^Wilma')
,('XXX-23343', 'Jer, Ronny^Wilma')
,('XXX-2349', 'Kel,Andy^Juka')
,('XXX-2349', 'Kel^Juka')
,('XXX-2998', 'Hel, Frank')
,('XXX-2998', 'Hel,Frank^Fenris')
,('XXX-3188', 'Mey, Marion')
,('XXX-3188', 'Mey, Marion^Paula')
,('XXX-3188', 'Schulz^Roma')
,('XXX-3218', 'Böntgen-Simnet,Dr. Regine^Cara')
,('XXX-3218', 'Simnet,Dr. Regine^Cara')
,('XXX-3826', 'Mertes, Bernd Uwe^Ellie')
,('XXX-3826', 'Mertes,Bernd^Ellie')
,('XXX-3826', 'Mertes^Ellie');
WITH DataSource AS
(
SELECT [ID]
,[Name]
,COUNT(*) OVER (PARTITION BY [ID], LTRIM(RTRIM(SUBSTRING([Name], 0, CHARINDEX(',', REPLACE([Name], '^', ',')))))) AS [ID_Name_Count]
,COUNT(*) OVER (PARTITION BY [ID]) AS [ID_Count]
,LTRIM(RTRIM(SUBSTRING([Name], 0, CHARINDEX(',', REPLACE([Name], '^', ','))))) AS [FamilyName]
FROM #DataSource
)
SELECT [ID]
,[Name]
FROM DataSource
WHERE [ID_Name_Count] = 1
AND [ID_Count] = 2
OR [ID] IN
(
SELECT [ID]
FROM DataSource
GROUP BY [ID]
HAVING COUNT(DISTINCT [FamilyName]) > 1
);
Тhe solution is pretty easy. Here are the interesting parts:
replace the ^ with , in order to simplify the last name extraction
extract the last name and calculation count based on ID and last name
in the final select check for unique id-last name pairs with id count equal to 2 and add ids with more then one unique family names (your special case)
You can try something like that:
Test data
drop table if exists #Patient;
create table #Patient (
PatientID varchar(20),
PatientName varchar(50)
);
insert into #Patient(PatientID,PatientName)
values ('XXX-037070002' ,'Riger, Jens^Wicki'),
('XXX-037070002' ,'Riger^Wicki'),
('XXX-10052' ,'Weier,Nicole^Peggy'),
('XXX-10052' ,'Weier,Nicole^Peppy'),
('XXX-23310' ,'Rodem^Sieglinde'),
('XXX-23310' ,'Sauberger, Birgit^Finja'),
('XXX-23343' ,'Je, Ronny^Wilma'),
('XXX-23343' ,'Jer, Ronny^Wilma'),
('XXX-2349' ,'Kel,Andy^Juka'),
('XXX-2349' ,'Kel^Juka'),
('XXX-2998' ,'Hel, Frank'),
('XXX-2998' ,'Hel,Frank^Fenris'),
('XXX-3188' ,'Mey, Marion'),
('XXX-3188' ,'Mey, Marion^Paula'),
('XXX-3188' ,'Schulz^Roma'),
('XXX-3218' ,'Böntgen-Simnet,Dr. Regine^Cara'),
('XXX-3218' ,'Simnet,Dr. Regine^Cara'),
('XXX-3826' ,'Mertes, Bernd Uwe^Ellie'),
('XXX-3826' ,'Mertes,Bernd^Ellie'),
('XXX-3826' ,'Mertes^Ellie');
My solution
with q1 as (
select
PatientID,
PatientName,
case when CHARINDEX(',',REPLACE( PatientName, '^',',')) > 0
then LEFT(PatientName,CHARINDEX(',',REPLACE( PatientName, '^',','))-1)
else PatientName end as FullName
from #Patient
) ,
q2 as (
select PatientID
from q1
group by PatientID having COUNT(1) > 1 and COUNT(DISTINCT FullName) > 1 )
select t.PatientID,t.PatientName
from #Patient t join q2 on t.PatientID = q2.PatientID;

How to transform select query

I have DDL:
drop table names
drop table salary
create table names(
id int,
name1 varchar(50),
char1 varchar(50),
char2 varchar(50))
insert into names values (1,'name1','char1','chara'),
(2,'name2','char2','charb'),
(3,'name3','char3','charc'),
(4,'name4','char4','chard'),
(5,'name5','char5','charf');
create table salary(
id int,
salary int,
bonus int,
oldsalary int)
insert into salary values (1,500,245,354),
(2,600,345,246),
(3,60,365,334),
(4,55,545,364),
(5,25,345,374);
And have the many SQL query' s (one of them)
SELECT n.name1,
s.salary,
s.bonus,
( s.bonus + s.salary ) AS Sumsalary
FROM names n
INNER JOIN salary s
ON n.id = s.id
I want to write select query that retrieves all fieldnames from tables that used in SQL query divided by usage in this select query with some additional info mentioned in screenshot.
Format of data that I want retrieve from this query:
You could get the list of tables & columns for queries if you have access to the system views:
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS ns)
SELECT DISTINCT st.TEXT AS QueryText,
C.value('./#Table', 'varchar(50)') As Tab,
C.value('./#Column', 'varchar(50)') As Col
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
CROSS APPLY query_plan.nodes('//ns:ColumnReference') as T(C)
WHERE cp.ObjType = 'Adhoc' AND
St.Text Like '%s.bonus%' AND
st.Text Not Like '%WITH XMLNAMESPACES%' AND
C.value('./#Table', 'varchar(50)') IS NOT NULL
This gives the following results:
QueryText Tab Col
SELECT n.name1, ... [Names] id
SELECT n.name1, ... [Names] name1
SELECT n.name1, ... [Salary] bonus
SELECT n.name1, ... [Salary] id
SELECT n.name1, ... [Salary] salary
You could then use these results as a means of linking to sys.columns to determine which coulmns are missing etc.

Create Distinct Column Values as Extra Rows

Any tricks anyone can share on how to manipulate the following table
ID TYPE Name Description
1 X A DESC_A
2 X B DESC_B
3 Z C DESC_C
to this view?
NAME_X DESCRIPTION_X
A DESC_A
B DESC_B
NAME_Z DESCRIPTION_Z
C DESC_C
For every distinct column, I would like to create a custom row for every distinct value in the 'TYPE' column. In this example, the custom row is created by appending the TYPE value to 'NAME_' and 'DESCRIPTION_'.
Thanks!
Try this:
create view vwTestDistinctData
as
select [type], [Description]
from testdistinctdata
union all
select
'NAME_' + [type] as [Type],
'DESCRIPTION_' + [type] as [Description]
from testdistinctdata
group by [type]
go
Edit: Return some meta data from the view:
alter view dbo.yourView
as
with c_Distinct([type])
as ( select distinct [Type]
from dbo.yourTable
)
select [Sort] = 0,
[Type],
Name,
[Description]
from dbo.yourTable
union all
select [Sort] = 1,
[Type],
'NAME_'+[Type],
'DESCRIPTION_'+[Type]
from c_Distinct
And then perform the ordering when selecting from the View:
select *
from yourView
order by [Type] asc, [Sort] desc