SQL Updating two records - sql

I am trying to update two employee's data. Let say one employee's id is 1234 and the other employee's id is 5678. Each employee has different services.
This is my table for reference
serv_id emp_id serv_name status
1 1234 computer1 A
5 1234 computer2 A
10 1234 computer3 A
37 1234 computer4 A
5 5678 computer2 A
11 5678 projector1 A
12 5678 projector2 A
30 5678 projector3 A
37 5678 computer4 A
35 5678 projector4 A
In the table above, we have 2 employees with 10 records and each employee has 5 services. What I want to do right now is to merge these two employee's services into one employee (1234) because employee 5678 is fired. However, serv_id with '5' or '37' does not need to be updated in employee 1234.
Here is my expected result. Let say A is active and I is inactive. Any suggestion on how to do it?
serv_id (pk) emp_id (fk) serv_name status
1 1234 computer1 A
5 (no update) 1234 computer2 A
10 1234 computer3 A
11 1234 projector1 A
12 1234 projector2 A
30 1234 projector3 A
35 1234 projector4 A
37 (no update) 1234 computer4 A
11 5678 projector1 I
37 5678 computer4 I
5 5678 computer2 I
11 5678 projector1 I
12 5678 projector2 I
30 5678 projector3 I
37 5678 computer4 I
35 5678 projector4 I

Try this
declare #tb as Table (serv_id int, emp_id int, serv_name nvarchar(20),status nvarchar(5))
insert into #tb
select 1 ,1234,'computer1','A' union
select 5 ,1234,'computer2','A' union
select 10,1234,'computer3','A' union
select 37,1234,'computer4','A' union
select 5 ,5678,'computer2','A' union
select 11,5678,'projector1','A' union
select 12,5678,'projector2','A' union
select 30,5678,'projector3','A' union
select 37,5678,'computer4','A' union
select 35,5678,'projector4','A'
update #tb set status ='I' where emp_id = 5678
insert into #tb select serv_id,1234,serv_name,'A' from #tb where emp_id=5678 and serv_id not in (select serv_id from #tb where emp_id=1234)
select * from #tb order by emp_id,serv_id

UPDATE t1
SET t1.status='I'
FROM my_table t1
LEFT OUTER JOIN my_table t2 ON t2.serv_name=t1.serv_name AND t2.emp_id=1234
WHERE t1.emp_id=5678
AND t2.serv_id IS NULL
We can join the table to itself by serv_name and emp_id to find common serv_names and then update only the records which have no same values for the emp_id=1234

Related

SQL - Group vacations in a table based on a holidays

Here is the sample data from the employee vacation table.
Emp_id Vacation_Start_Date Vacation_End_Date Public_Hday
1234 06/01/2022 06/07/2022 null
1234 06/08/2022 06/14/2022 null
1234 06/15/2022 06/19/2022 06/17/2022
1234 06/20/2022 06/23/2022 null
1234 06/24/2022 06/28/2022 null
1234 06/29/2022 07/02/2022 06/30/2022
1234 07/03/2022 07/07/2022 null
1234 07/08/2022 07/12/2022 null
1234 07/13/2022 07/17/2022 07/15/2022
1234 07/18/2022 07/22/2022 null
I want to group these vacations based on the public holidays in between (Assuming that all the vacations are consecutive). Here is the output that I am trying to get.
Emp_id Vacation_Start_Date Vacation_End_Date Public_Hday Group
1234 06/01/2022 06/07/2022 null 0
1234 06/08/2022 06/14/2022 null 0
1234 06/15/2022 06/19/2022 06/17/2022 1
1234 06/20/2022 06/23/2022 null 1
1234 06/24/2022 06/28/2022 null 1
1234 06/29/2022 07/02/2022 06/30/2022 2
1234 07/03/2022 07/07/2022 null 2
1234 07/08/2022 07/12/2022 null 2
1234 07/13/2022 07/17/2022 07/15/2022 3
1234 07/18/2022 07/22/2022 null 3
Here is the code that I tried
Select *, dense_rank() over (partition by Emp_id order by Public_Hday) - 1 AS Group from Emp_Vacation.
But, it gave the expected group values only to the vacations where the Public_Hday is not null. How do I get the group values to the other vacations.
You can use a conditional sum() over()
Select *
,Grp = sum( case when [Public_Hday] is null then 0 else 1 end ) over (partition by [Emp_id] order by [Vacation_Start_Date])
from YourTable
Results

update table column from view in another database in oracle sql developer

i have 2 database in oracle.
DATABASE TABLE/VIEW NAME
digidb1 CUSTOMER_REFERENCE
digidb2 CUST_REF_VIEW
this query will display all data in the table CUSTOMER_REFERENCE from db digidb1.
select * from CUSTOMER_REFERENCE
cust_id brch_code cust_name description
001 001 COMPANY TEST 1 TEST COMPANY 1
002 002 COMPANY TEST 2 TEST COMPANY 2
003 003 COMPANY TEST 3 TEST COMPANY 3
this query will display all data in the view CUST_REF_VIEW from db digidb2.
select * FROM CUST_REF_VIEW
WINBBN CUSTFULLNAME ISINDIVIDUAL MRGDATE
1234 COMPANY TEST 1 N 12-03-20
4567 COMPANY TEST 4 N 12-03-20
8901 COMPANY TEST 2 N 11-03-20
2345 COMPANY TEST 5 Y 10-03-20
6789 COMPANY TEST 3 N 12-03-20
is it possible to update the table(CUSTOMER_REFERENCE) from database(digidb1) with this data?
i want to update cust_id column in CUSTOMER_REFERENCE from digidb1. the data will come from view CUST_REF_VIEW of digidb2.
the condition for updates are:
CUSTFULLNAME is equal to cust_name
MRGDATE is equal to system date/today (12-03-20)
ISINDIVIDUAL is equal to N.
my expected result is:
cust_id brch_code cust_name description
1234 001 COMPANY TEST 1 TEST COMPANY 1
002 002 COMPANY TEST 2 TEST COMPANY 2
6789 003 COMPANY TEST 3 TEST COMPANY 3
If I understood you correctly, you don't actually want to update anything, but select data from those two views by joining them, using certain conditions. If that's so, then:
SQL> with
2 -- sample data
3 customer_reference (cust_id, brch_code, cust_name, description) as
4 (select '001', '001', 'CT1', 'TC1' from dual union all
5 select '002', '002', 'CT2', 'TC2' from dual union all
6 select '003', '003', 'CT3', 'TC3' from dual
7 ),
8 cust_ref_view (winbbn, custfullname, isindividual, mgrdate) as
9 (select '1234', 'CT1', 'N', date '2020-03-12' from dual union all
10 select '4567', 'CT4', 'N', date '2020-03-12' from dual union all
11 select '8901', 'CT2', 'N', date '2020-03-11' from dual union all
12 select '2345', 'CT5', 'Y', date '2020-03-10' from dual union all
13 select '6789', 'CT3', 'N', date '2020-03-12' from dual
14 )
15 -- query you need
16 select case when v.mgrdate = trunc(sysdate)
17 and v.isindividual = 'N'
18 then v.winbbn
19 else r.cust_id
20 end cust_id,
21 --
22 r.brch_code, r.cust_name, r.description
23 from customer_reference r join cust_ref_view v on v.custfullname = r.cust_name;
CUST BRC CUS DES
---- --- --- ---
1234 001 CT1 TC1
002 002 CT2 TC2
6789 003 CT3 TC3
SQL>
Now, depending on what you really call "database", a database link might to be be involved if those really are different databases, e.g.
from customer_reference r join cust_ref_view#db_link_digidb2 v
----------------
this
If it is just about different users (schemas) within the same database, then you'll need to grant (at least) SELECT privilege from one user to another. It also means that you'd need to precede remote view name with its owner name, e.g.
from customer_reference r join digidb2.cust_ref_view v
--------
this
or - a simpler option - to create a synonym in one schema which will point to view in another schema. In that case, line #23 in query I posted would look exactly the same.

Use Calendar table to generate historical view of the data

I have a created_date (timestamp) on 1 of my tables, that also has the duration column of a project, and I need to join with another table that only has first_day_of_month column that has the first day of each month, and other relevant information.
Table 1
id project_id created_date duration
1 12345 01/01/2015 10
2 12345 20/10/2015 11
3 12345 10/04/2016 13
4 12345 10/08/2016 15
Table 2
project_id month_start_date
12345 01/01/2015
12345 01/02/2015
12345 01/03/2015
12345 01/04/2015
...
12345 01/08/2016
Expected result
project_id month_start_date duration
12345 01/01/2015 10
12345 01/02/2015 10
...
12345 01/10/2015 11
12345 01/11/2015 11
...
12345 01/04/2016 13
12345 01/05/2016 13
12345 01/06/2016 13
...
12345 01/08/2016 15
I want to be able to present the data listed in my second table historically. So, basically I want the query to return the same duration related to the month_start_date, so that values will repeat until another dateadd(month,datediff(month,0,created_date),0) = first_day_of_month is met... and so forth.
This is my query:
select table2.project_name,
table2.month_start_date,
table1.duration,
table1.created_date
from table1 left outer join table2
on table1.project_id=table2.project_id
where dateadd(month,datediff(month,0,table1.created_date),0)<=table2.month_start_date
group by table2.project_name,table2.month_start_date,table1.duration,table1.created_date
order by table2.month_start_date asc
but I get repeated records on this:
Result I'm getting
project_id month_start_date duration
12345 01/01/2015 10
12345 01/02/2015 10
...
12345 01/10/2015 10
12345 01/10/2015 11
...
12345 01/04/2016 10
12345 01/04/2016 11
12345 01/04/2016 13
...
12345 01/08/2016 10
12345 01/08/2016 11
12345 01/08/2016 13
12345 01/08/2016 15
Can anyone help?
Thank you!
I'd use CROSS/OUTER APPLY operator.
Here is one possible variant. For each row in your calendar table Table2 (for each month) the inner correlated subquery inside the CROSS APPLY finds one row from Table1. It will be the row with the same project_id and the first row with created_date before the month_start_date plus 1 month.
SELECT
Table2.project_id
,Table2.month_start_date
,Durations.duration
FROM
Table2
CROSS APPLY
(
SELECT TOP(1) Table1.duration
FROM Table1
WHERE
Table1.project_id = Table2.project_id
AND Table1.created_date < DATEADD(month, 1, Table2.month_start_date)
ORDER BY Table1.created_date DESC
) AS Durations
;
Make sure that Table1 has index on (project_id, created_date) include (duration). Otherwise, performance would be poor.

Oracle 10g unpivot returning values in one column and creating month column

We just found out that the new database we have been given access to is Oracle 10g, so we are unable to use fcn like UNPIVOT.
We have a table like this..
SUBMISSION COUNTRY CPM_ID PFM_ID T_AREA CNTRY_CODE V_TYPE RES_CAT JAN_2014 FEB_2014
01-JUN-2014 USA 10 24 TEST1 USA V1 210 5 10
01-AUG-2014 UK 20 30 TEST2 UK V1 213 20 30
The desired output would look like this...
SUBMISSION COUNTRY CPM_ID PFM_ID T_AREA CNTRY_CODE V_TYPE RES_CAT MONTH VALUE
01-JUN-2014 USA 10 24 TEST1 USA V1 210 01-JAN-2014 5
01-JUN-2014 USA 10 24 TEST1 USA V1 210 01-FEB-2014 10
01-AUG-2014 UK 20 30 TEST2 UK V1 213 01-JAN-2014 20
01-AUG-2014 UK 20 30 TEST2 UK V1 213 01-FEB-2014 30
I am working with a query like this...but I cannot get the month column to come out right...
select *
from (select t.submission,
t.country,
t.cpm_id,
t.pfm_id,
t.t_area,
t.cntry_code,
t.v_type,
t.res_cat,
(case
when n.n = 1 then JAN-2014
when n.n = 1 then FEB-2014 end) as value
from table1 t cross join
(select FEB_2014 as n from dual union all
select FEB_2014 from dual) n
) s
where value is not null;
Thanks for your help,
I would do:
select t.submission,
t.country,
t.cpm_id,
t.pfm_id,
t.t_area,
t.cntry_code,
t.v_type,
t.res_cat,
n.d,
case when n.d = '01-JAN-2014' then t.jan_2014 else t.feb_2014 end value
from table1 t
cross join
(
select '01-JAN-2014' d from dual
union all
select '01-FEB-2014' d from dual
) n;

How to bring together multiple delta tables?

I have a table with IDs and primary information. I also have two delta tables keyed on ID and date of change. I need to build a view that merges these three tables together indicating all changes over time.
Main Table:
ID Name
-- ------------------
1 Bob Jones
2 Dave Smith
First Attribute Table:
ID Date Attr1
-- ---------- -----
1 01/01/2013 25
1 02/15/2013 33
1 02/17/2013 47
1 03/02/2013 58
2 02/01/2013 1
...
Second Attribute Table
ID Date Attr2
-- ---------- -----
1 01/01/2013 ABC
1 01/05/2013 DEF
1 01/15/2013 RST
1 02/10/2013 XYZ
1 02/15/2013 Foo
1 03/05/2013 Blah
2 02/01/2013 Two
...
Based on that data, for Bob Jones, I need the view to return the following:
ID Name Date Attr1 Attr2
-- ----------- ---------- ----- -----
1 Bob Jones 01/01/2013 25 ABC
1 Bob Jones 01/05/2013 25 DEF
1 Bob Jones 01/15/2013 25 RST
1 Bob Jones 02/10/2013 25 XYZ
1 Bob Jones 02/15/2013 33 Foo
1 Bob Jones 02/17/2013 47 Foo
1 Bob Jones 03/02/2013 58 Foo
1 Bob Jones 03/05/2013 58 Blah
I tried outer joining the attribute tables to get all change values ordered by date and then used an outer join on the entire query with itself to get "prior" records:
with qry as (
select
rownum = ROW_NUMBER() OVER (ORDER BY m.ID, a.DATE),
m.ID,
m.Name,
a.DATE,
a.Attr1,
a.Attr2
from Main m
inner join (
select
COALESCE(a1.ID, a2.ID) as ID,
COALESCE(a1.LOAD_DATE, a2.LOAD_DATE) as LOAD_DATE,
a1.Attr1,
a2.Attr2
from Attributes1 a1
full outer join Attributes2 a2
on (a1.ID = a2.ID and a1.DATE = a2.DATE)
) a on (a.ID = m.ID)
)
select
COALESCE(qry.ID, prev.ID) as ID,
COALESCE(qry.Name, prev.Name) as Name,
COALESCE(qry.DATE, prev.DATE) as DATE,
COALESCE(qry.Attr1, prev.Attr1) as Attr1,
COALESCE(qry.Attr2, prev.Attr2) as Attr2,
from qry
left join qry prev
on (prev.rownum = qry.rownum - 1)
order by ID, DATE
However, that doesn't work when one attribute table changes quicker than the other because the attributes that didn't change are null in the results of the attribute table join and if two nulls show up back-to-back, the coalesce will return a null when I need the last non-null value that was in that column.
Can this even be done in a view in SQL Server 2012?