want 2nd highest salary order by department wise - sql

create table #t
(id int,
deptid int,
sal int)
insert into #t values (1,1,1000),(2,1,2000),(3,1,3000),(4,2,2000),(5,2,3000),(6,2,6000)
SELECT * FROM #t
Expected output :
id deptid sal
2 1 2000
5 2 3000

;with cte as
(select *, row_number() over(partition by deptid order by sal desc) as rn
from #t)
select *
from cte
where rn = 2

;WITH CTE
AS
(
SELECT ID, deptid, sal, ROW_NUMBER() OVER(PARTITION BY deptid ORDER BY deptid) SR FROM #t
)
SELECT ID, deptid, sal FROM CTE WHERE SR = 2

Your required query
create table #t
(id int,
deptid int,
sal int)
insert into #t values (1,1,1000),(2,1,2000),(3,1,3000),(4,2,2000),(5,2,3000),(6,2,6000)
select * from (
SELECT id,deptid,sal,row_number() over(partition by deptid order by sal)rnum FROM #t
) as a
where rnum=2

Related

How to get row values in to columns in sql server with based on id

I have the following table:
id Prefix FisrtName LastName
--------------------------------------------
123 Mr Lynn Berg
123 Ms Madeline Owen
123 Mrs Zelenia Sellers
101 Mrs Jesse Vincent
101 Mr Chaim Long
The result table should look like this
id name1 name2 name2
-----------------------------------------------------------
123 Mr Lynn Berg Ms MadelineOwen Mrs Zelenia Sellers
101 Mrs Jesse Vincent Mr Chaim Long
How could I achieve this result in SQL Server? Can I use pivot function?
Please help
You can also do conditional aggregation :
select id, max(case when seq = 1 then Name end) as Name1,
max(case when seq = 2 then Name end) as Name2,
max(case when seq = 3 then Name end) as Name3
from (select id, concat(Prefix,' ',FisrtName,' ',LastName) as Name,
row_number() over (partition by id order by (select null)) as seq
from table
) t
group by id;
Try this simple pivot:
declare #tbl table (id int, Prefix varchar(3), FirstName varchar(20), LastName varchar(20));
insert into #tbl values
(123, 'Mr', 'Lynn', 'Berg'),
(123, 'Ms', 'Madeline', 'Owen'),
(123, 'Mrs', 'Zelenia', 'Sellers'),
(101, 'Mrs', 'Jesse', 'Vincent'),
(101, 'Mr', 'Chaim', 'Long');
select id, [1] [Name1], [2] [Name2], [3] [Name3] from (
select id,
ROW_NUMBER() over (partition by id order by (select null)) rn,
Prefix + ' ' + FirstName + ' ' + LastName [FullName]
from #tbl
) a pivot (
max(fullname) for rn in ([1],[2],[3])
) b;
CREATE TABLE #Table1 (
id INT
,Prefix VARCHAR(3)
,FisrtName VARCHAR(8)
,LastName VARCHAR(7)
);
INSERT INTO #Table1
VALUES (
123
,'Mr'
,'Lynn'
,'Berg'
)
,(
123
,'Ms'
,'Madeline'
,'Owen'
)
,(
123
,'Mrs'
,'Zelenia'
,'Sellers'
)
,(
101
,'Mrs'
,'Jesse'
,'Vincent'
)
,(
101
,'Mr'
,'Chaim'
,'Long'
)
SELECT *
FROM #Table1
SELECT id
,[1] [Name1]
,[2] [Name2]
,[3] [Name3]
FROM (
SELECT id
,CONCAT (
PREFIX
,FISRTNAME
,LASTNAME
) AS Namm
,ROW_NUMBER() OVER (
PARTITION BY id ORDER BY (
id
)
) AS rn
FROM #TABLE1
) a
pivot(max(Namm) FOR rn IN (
[1]
,[2]
,[3]
)) b

How to get rows from two tables on maximum value of particular field

I have two tables that has date_updated column.
TableA is like below
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
123 15/06/2018 1
123 01/05/2018 3
101 06/04/2018 1
101 05/03/2018 2
And I have TableB that also has the same structure
con_id date_updated type
--------------------------------------------
123 15/05/2018 2
123 01/05/2018 1
101 07/06/2018 1
The resultant table should have the data with the recent date
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
101 07/06/2018 1
Here the date_updated column is datetime datatype of sql server. I tried this by using group by and selecting the maximum date_updated. But i am not able to include column type in select statement. When i used type in group by ,the result is not correct as the type is also grouped. How can i query this. Please help
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER(Partition By con_id ORDER BY date_updated DESC) as seq
FROM
(SELECT * FROM TableA
UNION ALL
SELECT * FROM TableB) as tblMain) as tbl2
WHERE seq = 1
One method:
WITH A AS(
SELECT TOP 1 con_id,
date_updated,
type
FROM TableA
ORDER BY date_updated DESC),
B AS(
SELECT TOP 1 con_id,
date_updated,
type
FROM TableB
ORDER BY date_updated DESC),
U AS(
SELECT *
FROM A
UNION ALL
SELECT *
FROM B)
SELECT *
FROM U;
The 2 CTE's at the top get your most recent rows from the tables, and then the end statement unions them together.
For the benefit of the person who says this doesn't work:
USE Sandbox;
GO
CREATE TABLE tablea (con_id int, date_updated date, [type] tinyint);
CREATE TABLE tableb (con_id int, date_updated date, [type] tinyint);
GO
INSERT INTO tablea
VALUES
(123,'19/06/2018',2),
(123,'15/06/2018',1),
(123,'01/05/2018',3),
(101,'06/04/2018',1),
(101,'05/03/2018',2);
INSERT INTO tableb
VALUES
(123,'15/05/2018',2),
(123,'01/05/2018',1),
(101,'07/06/2018',1);
GO
WITH A AS(
SELECT TOP 1 con_id,
date_updated,
[type]
FROM TableA
ORDER BY date_updated DESC),
B AS(
SELECT TOP 1 con_id,
date_updated,
[type]
FROM TableB
ORDER BY date_updated DESC),
U AS(
SELECT *
FROM A
UNION ALL
SELECT *
FROM B)
SELECT *
FROM U;
GO
DROP TABLE tablea;
DROP TABLE tableb;
This returns the dataset:
con_id date_updated type
----------- ------------ ----
123 2018-06-19 2
101 2018-06-07 1
Which is identical to the OP's data:
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
101 07/06/2018 1
Hope this helps:
WITH combined
AS(
select * FROM tableA
UNION
select * FROM tableB)
SELECT t1.con_id,
t1.date_updated,
t1.type
FROM (
SELECT con_id,
date_updated,
type,
row_number() OVER(partition BY con_id ORDER BY date_updated DESC) AS rownumber
FROM combined) t1
WHERE rownumber = 1;
Can be done using window functions:
declare #TableA table (con_id int, date_updated date, [type] int)
declare #TableB table (con_id int, date_updated date, [type] int)
insert into #TableA values
(123, '2018-06-19', 2)
, (123, '2018-06-15', 1)
, (123, '2018-05-01', 3)
, (101, '2018-04-06', 1)
, (101, '2018-03-05', 2)
insert into #TableB values
(123, '2018-05-15', 2)
, (123, '2018-05-01', 1)
, (101, '2018-06-07', 1)
select distinct con_id
, first_value(date_updated) over (partition by con_id order by con_id, date_updated desc) as con_id
, first_value([type]) over (partition by con_id order by con_id, date_updated desc) as [type]
from
(Select * from #TableA UNION Select * from #TableB) x

Delete duplicate rows from a table and referenced table microsoft sql server

I have table Person :
PersonId | FirstName | LastName |
1 | 'John' | 'Doe' |
2 | 'Mike' | 'Test' |
3 | 'John' | 'Doe' |
4 | 'Mike' | 'Test' |
5 | 'John' | 'Doe' |
6 | 'John' | 'Doe' |
Table Customer :
CustomerId | PersonId |
1001 | 1 |
1002 | 2 |
1003 | 3 |
1004 | 4 |
1005 | 5 |
1006 | 6 |
I want to delete Customer 1003,1004,1005,1006 because their Persons are duplicate, but PersonId is not same.
This should check FirstName and LastName in Person table and delete the duplicates in Customer table , Then delete duplicates in Person table. ( 3,4,5,6 )
Sorry if similar questions has been asked before but I couldn't do this.
Check This.
We delete first from Customer table. First we find duplicate records by using Row_number() and deleting personid which have to rank more than 1.
Below Query show duplicate records :
select ROW_NUMBER () over ( partition by firstname,lastname order by
PersonId ) RID, PersonId,FirstName,LastName
from #Person
After finding Duplicates we delete it from customer table then Person.
delete from Customer where PersonId in
(
select distinct PersonId P from
( select ROW_NUMBER () over ( partition by firstname,lastname order by PersonId ) RID, PersonId,FirstName,LastName from #Person )a
where RID>1
)
delete from Person where PersonId in
(
select distinct PersonId P from
( select ROW_NUMBER () over ( partition by firstname,lastname order by PersonId ) RID, PersonId,FirstName,LastName from #Person )a
where RID>1
)
Use this query to view the duplicates:
with duplicatecte(personid,rownum)As
(
select personid ,
row_Number() over(partition by FirstName+LastName order by personid)
from #person
)
select b.personid,customerid from duplicatecte a
inner join #customer b on a.personid=b.personid where rownum>1
Modify this query to delete as below
with duplicatecte(personid,rownum)As
(
select personid ,
row_Number() over(partition by FirstName+LastName order by personid)
from #person
)
delete b
from duplicatecte a
inner join #customer b on a.personid=b.personid where rownum>1
Begin Tran
CREATE TABLE #Person(PersonId INT,FirstName NVARCHAR(50),LastName NVARCHAR(50))
CREATE TABLE #Customer (CustomerId INT,PersonId INT)
INSERT INTO #Person
SELECT 1,'John','Doe' UNION ALL
SELECT 2 ,'Mike','Test' UNION ALL
SELECT 3 ,'John','Doe' UNION ALL
SELECT 4 ,'Mike','Test' UNION ALL
SELECT 5 ,'John','Doe' UNION ALL
SELECT 6 ,'John','Doe'
INSERT INTO #Customer
SELECT 1001, 1 UNION ALL
SELECT 1002 ,2 UNION ALL
SELECT 1003 ,3 UNION ALL
SELECT 1004 ,4 UNION ALL
SELECT 1005,5 UNION ALL
SELECT 1006,6
GO
WITH CTE (PersonId, DuplicateCount)
AS
(
SELECT FirstName,
ROW_NUMBER() OVER(PARTITION BY FirstName,LastName ORDER BY FirstName,PersonId) AS DuplicateCount
FROM #Person
)
--Select * from CTE WHERE DuplicateCount>1
DELETE FROM CTE WHERE DuplicateCount >1
DELETE FROM #Customer WHERE PersonId NOT IN(SELECT PersonId FROM #Person)
Select * from #Person
SELECT * from #Customer
ROLLBACK TRAN
declare #tbl table
(pid int
)
;with cte
as
(
select t1.*,row_number() over (partition by firstname,lastname order by personid) as rownum
from
person t1
)
delete
from
cte
output deleted.personid into #tbl where rownum>1
delete from customer where personid in (select personid from #tbl)
This will work for you:
Declare #person As table
(
PersonId int,
FirstName varchar(25),
LastName varchar(25)
)
Declare #customer As table
(
CustomerId int,
PersonId int
)
Insert Into #person (PersonId,FirstName,LastName) values(1,'John','Doe')
Insert Into #person (PersonId,FirstName,LastName) values(2,'Mike','Test')
Insert Into #person (PersonId,FirstName,LastName) values(3,'John','Doe')
Insert Into #person (PersonId,FirstName,LastName) values(4,'Mike','Test')
Insert Into #person (PersonId,FirstName,LastName) values(5,'John','Doe')
Insert Into #person (PersonId,FirstName,LastName) values(6,'John','Doe')
Insert Into #customer(CustomerId,PersonId) values(1001,1)
Insert Into #customer(CustomerId,PersonId) values(1002,2)
Insert Into #customer(CustomerId,PersonId) values(1003,3)
Insert Into #customer(CustomerId,PersonId) values(1004,4)
Insert Into #customer(CustomerId,PersonId) values(1005,5)
Insert Into #customer(CustomerId,PersonId) values(1006,6)
select p.PersonId into #temp from #person p right join
(Select PersonId,FirstName,LastName, ROW_NUMBER() over (partition by FirstName,LastName Order by PersonId) rownumber
from #person ) a
on p.PersonId=a.PersonId where a.rownumber>1
delete from #customer where PersonId in (select PersonId from #temp)
delete from #person where PersonId in (select PersonId from #temp)
select *from #customer
select *from #person

Conditional selection of RowNum in SQL

I have written a query which returns me following data.
ID EmpFirstName EmpLastName RowNum
1 X Y 1
2 A B 1
3 A B 2
Now I want all records where RowNum is >1. For example, in this case I need 2 and 3 record in output.
If I put condition RowNum >1 then I will get only third record but I want 2 as well.
Assuming your query is this:
select ID, EmpFirstName, EmpLastName,
ROW_NUMBER() OVER (PARTITION BY EmpFirstName, EmpLastName ORDER BY ID) AS RowNum
FROM aTable
This is a classic query used to filter out any duplicate values.
In order effectively select all the records with the duplicate values I can suggest using the COUNT() window function:
;with a as (
select ID, EmpFirstName, EmpLastName,
ROW_NUMBER() OVER (PARTITION BY EmpFirstName, EmpLastName ORDER BY ID) AS RowNum,
COUNT(*) OVER (PARTITION BY EmpFirstName, EmpLastName) AS cnt
FROM aTable
)
SELECT * FROM a where cnt > 1
ORDER BY EmpFirstName, EmpLastName
To test it use this query:
drop table #tmp
CREATE table #tmp (ID int , EmpFirstName varchar(10) , EmpLastName varchar(10))
go
INSERT INTO #tmp VALUES
(1,'X','Y' )
,(2,'A','B')
,(3,'A','B')
,(4,'A','C')
,(5,'B','C')
,(6,'B','C')
;with a as (
select ID, EmpFirstName, EmpLastName,
ROW_NUMBER() OVER (PARTITION BY EmpFirstName, EmpLastName ORDER BY ID) AS RowNum,
COUNT(id) OVER (PARTITION BY EmpFirstName, EmpLastName) AS cnt
FROM #tmp
)
SELECT * FROM a where cnt > 1
ORDER BY EmpFirstName, EmpLastName
Result:
ID EmpFirstName EmpLastName RowNum cnt
----------- ------------ ----------- -------------------- -----------
2 A B 1 2
3 A B 2 2
5 B C 1 2
6 B C 2 2
I make sample data and use this query
CREATE table #tmp (ID int , EmpFirstName varchar(10) , EmpLastName varchar(10) ,RowNum int)
INSERT INTO #tmp VALUES
(1,'X','Y',1)
,(2,'A','B',1)
,(3,'A','B',2)
SELECT ID,EmpFirstName,EmpLastName,RowNum
FROM (
SELECT *
,ROW_NUMBER() OVER (ORDER BY ID) AS [NEWrownum]
FROM #tmp
) q
WHERE q.NEWrownum > 1
try this,
DECLARE #Result TABLE (ID INT, EmpFirstName VARCHAR(10), EmpLastName VARCHAR(10), RowNum INT)
INSERT INTO #Result
VALUES
(1, 'X', 'Y', 1)
,(2, 'A', 'B', 1)
,(3, 'A', 'B', 2)
SELECT r1.*
FROM #Result r1
INNER JOIN (SELECT * -- get duplicate records
FROM #Result
WHERE RowNum = 2
) as r2 ON r1.EmpFirstName = r2.EmpFirstName
AND r1.EmpLastName = r2.EmpLastName

How to set partition id/name for row partitions in SQL Server?

How to set partition id/name for row partitions in SQL Server?
name surname val
a b 10
c d 2
a b 11
a b 13
result (partitioned by name and surname):
name surname val rowno partitionid
a b 10 1 1
a b 11 2 1
a b 13 3 1
c d 2 1 2
DECLARE #table TABLE( name CHAR(1) , surname CHAR(1) , val TINYINT )
INSERT INTO #table
VALUES ( 'a' , 'b' , 10 )
, ( 'c' , 'd' , 2 )
, ('a' , 'b' , 11 )
, ( 'a' , 'b' , 13 )
SELECT * FROM #table
SELECT *
, ROW_NUMBER() OVER ( PARTITION BY name, surname ORDER BY val ) as rowno
, DENSE_RANK() OVER ( ORDER BY name ) as partitionid
FROM #table
Regards!
The dense_rank window function seems to fit the bill:
SELECT *,
DENSE_RANK() OVER (PARTITION BY name, surname ORDER BY val) AS rowno,
DENSE_RANK() OVER (ORDER BY name, surname) AS partitionid
FROM mytable