How to show two columns as rows in SQL Server? - sql-server

Convert two column to rows in SQL Server

by Simple Cross Apply
DECLARE #Table1 TABLE
(ID int,installdate varchar(20),uninstalldate varchar(20))
;
INSERT INTO #Table1
(ID,installdate,uninstalldate)
VALUES
(1,'15/06/2016','18/06/2016'),
(2,'20/06/2016','25/06/2016')
Script :
select COL AS [Instal OR Uninstall],VAL AS [Date] from #Table1
CROSS APPLY
(VALUES
('installdate',installdate),
('uninstalldate',installdate))
CS(COL,VAL)

Simple UNPIVOT should do thing:
SELECT [DATES],
[VALUES]
FROM MyTable
UNPIVOT (
[VALUES] FOR [DATES] IN (InstallDate,UnInstallDate)
) as unpvt
Output:
DATES VALUES
InstallDate 2016-06-15
UnInstallDate 2016-06-18
InstallDate 2016-06-20
UnInstallDate 2016-06-25

You can UNPIVOT the columns into rows:
DECLARE #Data TABLE (
Id INT,
InstallDate DATE,
UnInstallDate DATE
)
INSERT #Data VALUES (1,'6/15/2016', '6/18/2016'),(2,'6/20/2016', '6/25/2016')
SELECT
ActivityType,
ActivityDate
FROM #Data
UNPIVOT (ActivityDate FOR ActivityType IN (InstallDate, UnInstallDate)) T
This produces the following rows:
ActivityType ActivityDate
------------------------- ------------
InstallDate 2016-06-15
UnInstallDate 2016-06-18
InstallDate 2016-06-20
UnInstallDate 2016-06-25

Related

How to reference the current column you are defining using lag?

I have a salary table like this:
declare #t table (OrderedID int, EmpID int, EffDate date, Salary money)
insert into #t
values
(1,1234,'20150101',100)
,(2,1234,'20160101',100)
,(3,1234,'20170101',100)
,(4,1234,'20180101',300)
,(1,2351,'20150101',100)
I am trying to get an initial effective date on each row:
First 3 rows have 1/1/2015
4th row has new value 1/1/2018
Here is what I tried with a case and a lag but i can't figure out how to reference the prior value of the column I am creating.
case when OrderedID = 1 then EFFDaTe
when Salary != LAG(Salary,1) then EFFDaTe
else lag(SalaryEFFDT,1) over (order by 1)
end as SalaryEFFDT
Thanks for your help.
As you haven't provided the expected output, I think this is what you want:
declare #t table (OrderedID int, EmpID int, EffDate date, Salary money)
insert into #t
values
(1,1234,'20150101',100)
,(2,1234,'20160101',100)
,(3,1234,'20170101',100)
,(4,1234,'20180101',300)
,(1,2351,'20150101',100)
,(5,1234,'20190101',100)
;with cte as
(Select *, OrderedId - Row_Number() over (partition by EmpId,Salary order by OrderedID) as grp
from #t)
, cte1 as
(Select EmpID, grp, min(effDate) as effDate from cte c group by EmpID, grp)
Select OrderedID, t.EmpID, t.EffDate, t.Salary, c.effDate as computeddate
from cte t join cte1 c on t.EmpID = c.EmpID and t.grp = c.grp
order by OrderedID
So you are trying to get the first effective date for each EmpID? the code below should do that. If that is not your desired output can you put what the output should look like?
declare #t table (OrderedID int, EmpID int, EffDate date, Salary money)
insert into #t
values
(1,1234,'20150101',100)
,(2,1234,'20160101',100)
,(3,1234,'20170101',100)
,(4,1234,'20180101',300)
,(1,2351,'20140101',100)
,(2,2351,'20150101',100)
Select
T.*,FE.FirstEff
From #t T
inner join (Select EmpID,MIN(EffDate) as FirstEff from #t group by
The second set is if you need the first time they have that salary, however you will have issues if someone gets a raise and then a demotion.
Select
T.*,FE.FirstEff
From #t T
inner join (Select EmpID,Salary,MIN(EffDate) as FirstEff from #t group by EmpID,Salary) FE on FE.EmpID = T.EmpID
and FE.Salary = T.Salary

Sql server table has has month name as column, how to convert into multiple rows datewise [duplicate]

I have a scenario where I need to convert columns of table to rows
eg -
table - stocks:
ScripName ScripCode Price
-----------------------------------------
20 MICRONS 533022 39
I need to represent the table in the following format, but I just need this kind of representation for single row
ColName ColValue
-----------------------------
ScripName 20 MICRONS
ScripCode 533022
Price 39
so that I can directly bind the data to the datalist control.
Sound like you want to UNPIVOT
Sample from books online:
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Returns:
VendorID Employee Orders
---------- ---------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
see also: Unpivot SQL thingie and the unpivot tag
declare #T table (ScripName varchar(50), ScripCode varchar(50), Price int)
insert into #T values ('20 MICRONS', '533022', 39)
select
'ScripName' as ColName,
ScripName as ColValue
from #T
union all
select
'ScripCode' as ColName,
ScripCode as ColValue
from #T
union all
select
'Price' as ColName,
cast(Price as varchar(50)) as ColValue
from #T
select 'ScriptName', scriptName from table
union all
select 'ScriptCode', scriptCode from table
union all
select 'Price', price from table
As an alternative:
Using CROSS APPLY and VALUES performs this operation quite simply and efficiently with just a single pass of the table (unlike union queries that do one pass for every column)
SELECT
ca.ColName, ca.ColValue
FROM YOurTable
CROSS APPLY (
Values
('ScripName' , ScripName),
('ScripCode' , ScripCode),
('Price' , cast(Price as varchar(50)) )
) as CA (ColName, ColValue)
Personally I find this syntax easier than using unpivot.
NB: You must take care that all source columns are converted into compatible types for the single value column
DECLARE #TABLE TABLE
(RowNo INT,ScripName VARCHAR(10),ScripCode VARCHAR(10)
,Price VARCHAR(10))
INSERT INTO #TABLE VALUES
(1,'20 MICRONS ','533022','39')
SELECT ColumnName,ColumnValue from #Table
Unpivot(ColumnValue For ColumnName IN (ScripName,ScripCode,Price)) AS H
i solved the query this way
SELECT
ca.ID, ca.[Name]
FROM [Emp2]
CROSS APPLY (
Values
('ID' , cast(ID as varchar)),
('[Name]' , Name)
) as CA (ID, Name)
output look like
ID Name
------ --------------------------------------------------
ID 1
[Name] Joy
ID 2
[Name] jean
ID 4
[Name] paul
CREATE TABLE #ORIGINAL
(
COUNTRY VARCHAR(50),
MALE_CRICKETER VARCHAR(50),
FEMALE_CRICKETER VARCHAR(50),
MALE_STAR VARCHAR(50),
FEMALE_STAR VARCHAR(50),
)
select * from #ORIGINAL
SELECT COUNTRY, ca.GENDER, ca.STAR, ca.CRICKETR
FROM #ORIGINAL
CROSS APPLY (
Values
('M', MALE_CRICKETER, MALE_STAR),
('F', FEMALE_CRICKETER, FEMALE_STAR)
) as CA (GENDER, CRICKETR, STAR)

Getting the last row from a ROW_NUMBER using SQL

I am thinking there is a better way to grab the last row from a row_number instead of doing multiple nesting using T-SQL.
I need the total number of orders and the last ordered date. Say I have the following:
DECLARE #T TABLE (PERSON_ID INT, ORDER_DATE DATE)
INSERT INTO #T VALUES(1, '2016/01/01')
INSERT INTO #T VALUES(1, '2016/01/02')
INSERT INTO #T VALUES(1, '2016/01/03')
INSERT INTO #T VALUES(2, '2016/01/01')
INSERT INTO #T VALUES(2, '2016/01/02')
INSERT INTO #T VALUES(3, '2016/01/01')
INSERT INTO #T VALUES(3, '2016/01/02')
INSERT INTO #T VALUES(3, '2016/01/03')
INSERT INTO #T VALUES(3, '2016/01/04')
What I want is:
PERSON_ID ORDER_DATE ORDER_CNT
1 2016-01-03 3
2 2016-01-02 2
3 2016-01-04 4
Is there a better way to do this besides the following:
SELECT *
FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY PERSON_ID ORDER BY ORDER_CNT DESC) AS LAST_ROW
FROM (
SELECT *
, ROW_NUMBER () OVER (PARTITION BY PERSON_ID ORDER BY ORDER_DATE) AS ORDER_CNT
FROM #T
) AS A
) AS B
WHERE LAST_ROW = 1
Yes, you can use this:
SELECT
PERSON_ID,
MAX(ORDER_DATE) AS ORDER_DATE,
COUNT(*) AS ORDER_CNT
FROM #T
GROUP BY PERSON_ID
SELECT a.PERSON_ID
, a.ORDER_DATE
, a.ORDER_CNT
FROM
(
SELECT PERSON_ID
, ORDER_DATE
, rn = ROW_NUMBER () OVER (PARTITION BY PERSON_ID ORDER BY ORDER_DATE DESC)
, ORDER_CNT = COUNT(ORDER_DATE) OVER (PARTITION BY PERSON_ID)
FROM #T
) AS a
WHERE rn = 1
ORDER BY a.PERSON_ID;

Converting Columns into rows with their respective data in sql server

I have a scenario where I need to convert columns of table to rows
eg -
table - stocks:
ScripName ScripCode Price
-----------------------------------------
20 MICRONS 533022 39
I need to represent the table in the following format, but I just need this kind of representation for single row
ColName ColValue
-----------------------------
ScripName 20 MICRONS
ScripCode 533022
Price 39
so that I can directly bind the data to the datalist control.
Sound like you want to UNPIVOT
Sample from books online:
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Returns:
VendorID Employee Orders
---------- ---------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
see also: Unpivot SQL thingie and the unpivot tag
declare #T table (ScripName varchar(50), ScripCode varchar(50), Price int)
insert into #T values ('20 MICRONS', '533022', 39)
select
'ScripName' as ColName,
ScripName as ColValue
from #T
union all
select
'ScripCode' as ColName,
ScripCode as ColValue
from #T
union all
select
'Price' as ColName,
cast(Price as varchar(50)) as ColValue
from #T
select 'ScriptName', scriptName from table
union all
select 'ScriptCode', scriptCode from table
union all
select 'Price', price from table
As an alternative:
Using CROSS APPLY and VALUES performs this operation quite simply and efficiently with just a single pass of the table (unlike union queries that do one pass for every column)
SELECT
ca.ColName, ca.ColValue
FROM YOurTable
CROSS APPLY (
Values
('ScripName' , ScripName),
('ScripCode' , ScripCode),
('Price' , cast(Price as varchar(50)) )
) as CA (ColName, ColValue)
Personally I find this syntax easier than using unpivot.
NB: You must take care that all source columns are converted into compatible types for the single value column
DECLARE #TABLE TABLE
(RowNo INT,ScripName VARCHAR(10),ScripCode VARCHAR(10)
,Price VARCHAR(10))
INSERT INTO #TABLE VALUES
(1,'20 MICRONS ','533022','39')
SELECT ColumnName,ColumnValue from #Table
Unpivot(ColumnValue For ColumnName IN (ScripName,ScripCode,Price)) AS H
i solved the query this way
SELECT
ca.ID, ca.[Name]
FROM [Emp2]
CROSS APPLY (
Values
('ID' , cast(ID as varchar)),
('[Name]' , Name)
) as CA (ID, Name)
output look like
ID Name
------ --------------------------------------------------
ID 1
[Name] Joy
ID 2
[Name] jean
ID 4
[Name] paul
CREATE TABLE #ORIGINAL
(
COUNTRY VARCHAR(50),
MALE_CRICKETER VARCHAR(50),
FEMALE_CRICKETER VARCHAR(50),
MALE_STAR VARCHAR(50),
FEMALE_STAR VARCHAR(50),
)
select * from #ORIGINAL
SELECT COUNTRY, ca.GENDER, ca.STAR, ca.CRICKETR
FROM #ORIGINAL
CROSS APPLY (
Values
('M', MALE_CRICKETER, MALE_STAR),
('F', FEMALE_CRICKETER, FEMALE_STAR)
) as CA (GENDER, CRICKETR, STAR)

How to get a record base on date from a group using T-SQL

Here is the data
Flag Zone Info Date
R North AAA 2010-2-14
R North AAA 2010-2-24
T North AAA 2010-2-4
R South AAA 2010-2-23
T South AAA 2010-2-14
R EAST AAA 2010-2-22
T EAST AAA 2010-2-11
T EAST AAA 2010-2-1
T EAST AAA 2010-2-14
R WEST AAA 2010-2-29
Here is a table in the SQL SERVER, now I want to get a record from each group based on Zone column. The Flag field of this record should be R, and the Date should be the closest and after today's date.
Best Regards,
Using ROW_NUMBER you can try
DECLARE #Table TABLE(
Flag VARChAR(1),
Zone VARCHAR(10),
Info VARCHAR(10),
Date DATETIME
)
INSERT INTO #Table SELECT 'R','North','AAA','2010-2-14'
INSERT INTO #Table SELECT 'R','North','AAA','2010-2-24'
INSERT INTO #Table SELECT 'T','North','AAA','2010-2-4'
INSERT INTO #Table SELECT 'R','South','AAA','2010-2-23'
INSERT INTO #Table SELECT 'T','South','AAA','2010-2-14'
INSERT INTO #Table SELECT 'R','EAST',' AAA','2010-2-22'
INSERT INTO #Table SELECT 'T','EAST',' AAA','2010-2-11'
INSERT INTO #Table SELECT 'T','EAST',' AAA','2010-2-1'
INSERT INTO #Table SELECT 'T','EAST',' AAA','2010-2-14'
INSERT INTO #Table SELECT 'R','WEST',' AAA','2010-2-28'
;WITH Dates AS(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Zone ORDER BY Date) ROWID
FROM #Table
WHERE Flag = 'R'
AND Date > GETDATE()
)
SELECT *
FROM Dates
WHERE ROWID = 1
If you cannot use ROW_NUMBER you could try
SELECT t.*
FROM (
SELECT Zone,
MAX(Date) MaxDate
FROM #Table
WHERE Flag = 'R'
AND Date > GETDATE()
GROUP BY Zone
) Dates INNER JOIN
#Table t ON Dates.Zone = t.Zone and Dates.MaxDate = t.Date
But this will not exclude duplicates...

Resources