Updating the first occurrence of the column with a value and the remaining with other value - sql

select emp_id, emp_dept, emp_name
from employee
where emp_id in (123, 234);
emp_id emp_dept emp_name
*****************************
123 222 1234
123 222 5678
123 222 9101
234 222 1011
234 222 1112
234 222 1213
Here there are 3 records for each emp_id.
I want a query to update the emp_dept such that out of three records, only one record will be updated to 555(it can be any record doesnt matter) and the other 2 will be updated to 666.

Create a CTE (common table expression) adding a ROW_NUMBER window function partitioned by emp_id then write an update statement joining the cte and building a case statement to determine row number
The code below builds a Table Variable with Test data, selects the data to show you the "before" and then modifies with the cte method and selects the data to show you the final result.
;WITH cte AS (
SELECT
emp_id
,ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY emp_SSN) AS RowNum
FROM
#Table
)
UPDATE t
SET emp_dept = CASE WHEN RowNum = 1 THEN 555 ELSE 666 END
FROM
#Table t
INNER JOIN cte u
ON t.emp_id = u.emp_id

You can use MERGE.
Data Preparation
create table em1(
emp_id number, emp_dept number, emp_name varchar2(10));
insert into em1 values(123,1,'we');
insert into em1 values(123,1,'asd');
insert into em1 values(123,1,'rfw');
insert into em1 values(345,2,'rtg');
insert into em1 values(345,2,'bfg');
insert into em1 values(345,2,'uyi');
commit;
Query
MERGE INTO em1 e
USING (
SELECT emp_id, emp_dept, emp_name,
row_number() over (partition by emp_id order by 1) r
FROM em1
WHERE emp_id in (123,345)
) f
ON (f.emp_id = e.emp_id and f.emp_name = e.emp_name)
WHEN MATCHED THEN
UPDATE SET e.emp_dept = case when f.r = 1 then 555 else 666 end;
Result
emp_id emp_dept emp_name
-------------------------
123 555 we
123 666 asd
123 666 rfw
345 555 rtg
345 666 bfg
345 666 uyi

Related

More than one occurrence from table

create table customer (cif number, name varchar(20),mobile number);
insert into table customer values(121,'ANT',789);
insert into table customer values(122,'ANT',789);
insert into table customer values(123,'ENT',789);
insert into customer values(124,'ENT',789);
insert into customer values(125,'BEE',123);
insert into customer values(126,'BEE',123);
insert into customer values(127,'BRO',789);
insert into customer values(128,'FIO',789);
commit;
I want retrieve data from customer table based on name and mobile more than one occurrences.
Can anyone help me out
Result like
You can use COUNT() aggregation as Analytic function along with grouping by those columns through use of PARTITION BY clause as
SELECT cif, name, mobile
FROM (SELECT c.*,
COUNT(*) OVER (PARTITION BY name, mobile) AS cnt
FROM customer c )
WHERE cnt > 1
Demo
Source:
SQL> select * From customer;
CIF NAME MOBILE
---------- -------------------- ----------
121 ANT 789
122 ANT 789
123 ENT 789
124 ENT 789
125 BEE 123
126 BEE 123
127 BRO 789
128 FIO 789
8 rows selected.
Based on result you posted, you're looking for rows that aren't unique per name and mobile. If that's so, here's another option:
SQL> select *
2 from customer a
3 where exists (select null
4 from customer b
5 where b.name = a.name
6 and b.mobile = a.mobile
7 group by b.name, b.mobile
8 having count(*) > 1
9 );
CIF NAME MOBILE
---------- -------------------- ----------
121 ANT 789
122 ANT 789
123 ENT 789
124 ENT 789
125 BEE 123
126 BEE 123
6 rows selected.
SQL>

Update using joins by finding the previous value in sql

I have two tables and I have to update the address field in the emp table by looking up in the emphistory table with previous value i.e USA for employee John
Table emp
EId ename sal Address AccountId
-------------------------------
101 John 100 U X12
102 Peter 500 Null X13
Table emphistory
emphisid EId AccountId Address Date (use row_number to find the second record for that eid and accountid)
-----------------------------------------------------
1 101 X12 U 11-01-2020 09:45:00
2 102 X13 Null 11-01-2020 09:46:00
3. 101 X12 USA 11-01-2020 09:30:00
I have to join the tables with account id and eid.
This works in Postgresql & Sql Server
UPDATE emp
SET Address = hist.Address
FROM (
SELECT h.EId, h.AccountId, h.Address
, ROW_NUMBER() OVER (PARTITION BY h.EId, h.AccountId
ORDER BY h.Date DESC) AS Rn
FROM emphistory h
JOIN emp e
ON e.EId = h.EId
AND e.AccountId = h.AccountId
WHERE h.Address IS NOT NULL
) hist
WHERE emp.EId = hist.EId
AND hist.Rn = 2

Remove duplicate rows in Postgres

I have two tables:
Employee:
ID
Name
Surname
143
Amy
Flowers
245
Natasha
Smith
365
John
Alexander
445
Natasha
Smith
565
Monica
Withhouse
644
Amy
Flowers
1023
Amy
Alexander
And employee_details:
ID
Employee_id
Document_numer
1
644
XXXXXXXXX
2
245
XXXXXX
3
365
XXXXXX
I need to remove duplicate records that are in the Employee table and that are not related to the employee_details table. In the example data, I would like to delete the employee doublet with the id 143 and 445.
And I must admit that I have no idea how to do it.Could you give me a hint?
The base is postgres
Delete from Employee
Where id not in (
Select Employee_id
from employee_details
)
and name in (
Select name
from Employee
Group by name having count(name) > 1
)
Though the question is already answered I am adding two different answers here using cte.
create table Employee(ID int, Name varchar(50), Surname varchar(50));
insert into Employee values(143, 'Amy', 'Flowers');
insert into Employee values(245, 'Natasha', 'Smith');
insert into Employee values(365, 'John', 'Alexander');
insert into Employee values(445, 'Natasha', 'Smith');
insert into Employee values(565, 'Monica', 'Withhouse');
insert into Employee values(644, 'Amy', 'Flowers');
insert into Employee values(1023, 'Amy', 'Alexander');
create table employee_details ( ID int, Employee_id int, Document_numer varchar(50));
insert into employee_details values(1, 644, 'XXXXXXXXX');
insert into employee_details values(2, 245, 'XXXXXX');
insert into employee_details values(3, 365, 'XXXXXX');
Delete query 1:
with duplicate_employees as
(
select * , count(id)over(partition by name,surname) duplicate_count from Employee
)
delete from Employee where id in(
select id from duplicate_employees de
where duplicate_count >1
and not exists
(
select 1 from employee_details e where e.Employee_id = de.ID
)
)
select * from employee
Output:
id
name
surname
245
Natasha
Smith
365
John
Alexander
565
Monica
Withhouse
644
Amy
Flowers
1023
Amy
Alexander
db<>fiddle here
Delete query 2:
with cte as
(
Select *, count(*)over(partition by name,surname) duplicate_count,
(case when exists
(
select 1 from employee_details ed where ed.Employee_id = e.ID
)
then 1 else 0 end) exist_in_details
from Employee e
)
delete from Employee where id in (select id from cte where duplicate_count>1 and exist_in_details=0 )
select * from Employee
Output:
id
name
surname
245
Natasha
Smith
365
John
Alexander
565
Monica
Withhouse
644
Amy
Flowers
1023
Amy
Alexander
db<>fiddle here

How to write case for empty record in sql

I am having two table
Employee 1
Emp_Id Name Old_Id
111 Hemant 1
222 Sachin 2
Employee
Emp_ID Name Temp_Name
1 Hemant NULL
2 Sachin NULL
3 Vinod NULL
4 Nitin 1
5 Ajit 2
6 Suraj 3
I want to replace Temp_Name in Employee table by its new value available in Employee1 table.
Employee.Temp_Name is Employee1.Old_Id
Condition
1 : if Temp_Name is not present in Employee1.Old_id column it should be retained.
2 : Without creating any function.
The final output should be :
Employee
Emp_ID Name Short_Name
1 Hemant NULL
2 Sachin NULL
3 Vinod NULL
4 Nitin 111
5 Ajit 222
6 Suraj 3
I tried this
Update [Employee]
set
Temp_Name = (
select CASE Emp_ID
WHEN NULL THEN [Employee].Temp_Name
ELSE Emp_ID
END AS Emp_ID
from [Employee1] e1
where e1.old_id = [Employee].Temp_Name
)
But it gives me output :
Employee
Emp_ID Name Temp_Name
1 Hemant NULL
2 Sachin NULL
3 Vinod NULL
4 Nitin 111
5 Ajit 222
6 Suraj NULL
You can use LEFT JOIN with a combination of CASE expression.
SQL Fiddle
SELECT
e.Emp_Id,
e.Name,
Short_Name =
CASE
WHEN e1.Old_Id IS NOT NULL THEN e1.Emp_Id
ELSE e.Short_Name
END
FROM Employee e
LEFT JOIN Employee1 e1
ON e1.Old_Id = e.Short_Name
UPDATE statement
UPDATE e
SET e.Short_Name = e1.Emp_Id
FROM Employee e
LEFT JOIN Employee1 e1
ON e1.Old_Id = e.Short_Name
WHERE e1.Old_Id IS NOT NULL
EDIT: This is for sql server.
Here's the code I have with inserting the sample data:
begin tran
create table Employee1
(
Emp_Id int,
Name varchar(50),
Old_Id int
);
create table Employee
(
Emp_Id int,
Name varchar(50),
Short_Name int NULL
);
insert into Employee1
values(111, 'Hemant', 1);
insert into Employee1
values(222, 'Sachin', 2);
insert into Employee
values(1, 'Hemant', NULL);
insert into Employee
values(2, 'Sachin', NULL);
insert into Employee
values(3, 'Vinod', NULL);
insert into Employee
values(4, 'Nitin', 1);
insert into Employee
values(5, 'Ajit', 2);
insert into Employee
values(6, 'Suraj', 3);
update emp
set
emp.Short_Name = CASE
WHEN emp1.Emp_Id IS NULL THEN emp.Short_Name
ELSE emp1.Emp_Id
END
from
Employee emp
left join Employee1 emp1
on (emp.Short_Name = emp1.Old_Id)
select * From Employee
drop table Employee1
drop table Employee
rollback
You had to ensure you left join your tables.

sql that identifies which account numbers have multiple agents

I dont think a count will work here, can someone help me get an sql that identifies which account numbers have multiple agents, more than two agents in the where condition.
AGENT_NAME ACCOUNT_NUMBER
Clemons, Tony 123
Cipollo, Michael 123
Jepsen, Sarah 567
Joanos, James 567
McMahon, Brian 890
Novak, Jason 437
Ralph, Melissa 197
Reitwiesner, John 221
Roman, Marlo 123
Rosenzweig, Marcie 890
Results should be something like this.
ACCOUNT_NUMBER AGENT_NAME
123 Cipollo, Michael
123 Roman, Marlo
123 Clemons, Tony
890 Rosenzweig, Marcie
890 McMahon, Brian
567 Joanos, James
567 Jepsen, Sarah
You can do this using window functions:
select t.account_number, t.agent_name
from (select t.*, min(agent_name) over (partition by account_number) as minan,
max(agent_name) over (partition by account_number) as maxan
from table t
) t
where minan <> maxan;
If you know the agent names are never duplicated, you could just do:
select t.account_number, t.agent_name
from (select t.*, count(*) over (partition by account_number) as cnt
from table t
) t
where cnt > 1;
Assuming your table name is test, this should pull all the records with duplicate ACCOUNT_NUMBER:
select * from test where ACCOUNT_NUMBER in
(select ACCOUNT_NUMBER from test
group by ACCOUNT_NUMBER having
count(ACCOUNT_NUMBER)>1)
order by ACCOUNT_NUMBER
Using count function u can get the result
CREATE TABLE #TEMP
(
AGENT_NAME VARCHAR(100),
ACCOUNT_NUMBER INT
)
INSERT INTO #TEMP
VALUES ('CLEMONS, TONY',123),
('CIPOLLO, MICHAEL',123),
('JEPSEN, SARAH',567),
('JOANOS, JAMES',567),
('MCMAHON, BRIAN',890),
('NOVAK, JASON',437),
('RALPH, MELISSA',197),
('REITWIESNER, JOHN',221),
('ROMAN, MARLO',123),
('ROSENZWEIG, MARCIE',890)
SELECT a.ACCOUNT_NUMBER,a.AGENT_NAME
FROM #TEMP A
JOIN(SELECT COUNT(1) CNT,
ACCOUNT_NUMBER
FROM #TEMP
GROUP BY ACCOUNT_NUMBER) B
ON A.ACCOUNT_NUMBER = B.ACCOUNT_NUMBER
WHERE B.CNT != 1