Oracle SELECT statement [duplicate] - oracle

This question already has answers here:
Get top results for each group (in Oracle)
(5 answers)
First two salaries in each department [duplicate]
(3 answers)
Limit SQL query to only the top two counts per group [duplicate]
(1 answer)
Closed 2 months ago.
This post was edited and submitted for review 2 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I am trying to select the Top 5 best-selling products in terms of quantity per year.
CREATE TABLE purchaseorderheader(
purchaseorderid NUMBER(4),
revisionnumber NUMBER(2),
status NUMBER(1),
employeeid NUMBER(3),
vendorid NUMBER(4),
shipmethodid NUMBER(1),
orderdate TIMESTAMP,
shipdate TIMESTAMP,
subtotal FLOAT(10),
taxamt FLOAT(10),
freight FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderid)
);
CREATE TABLE purchaseorderdetail(
purchaseorderid NUMBER(4),
purchaseorderdetailid NUMBER(4),
duedate TIMESTAMP,
orderqty NUMBER(6),
productid NUMBER(6),
unitprice FLOAT(10),
receivedqty FLOAT(10),
rejectedqty FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderdetailid),
CONSTRAINT fk_orderid FOREIGN KEY (purchaseorderid) REFERENCES purchaseorderheader(purchaseorderid)
);
Here's what I've done so far but it's not by year and I have no clue of how to do it...
SELECT EXTRACT(year FROM h.orderdate) "Year", d.productid, SUM(d.orderqty) "Somme"
FROM purchaseorderheader h
INNER JOIN purchaseorderdetail d ON h.purchaseorderid = d.purchaseorderid
GROUP BY EXTRACT(year FROM h.orderdate), d.productid
ORDER BY "Somme"
DESC FETCH FIRST 5 ROWS ONLY;
I also would like to select The Top 5 vendors who have the lowest percentage of rejected received items if you have any idea

Related

Oracle Trigger on two tables

I am trying to create a BEFORE UPDATE trigger on the two tables purchaseorderdetail and purchaseorderheader as shown below. I would like to implement this trigger on PurchaseOrderHeader table that prohibits updates of the PurchaseOrderHeader.SubTotal column if the corresponding data in the PurchaseOrderDetail table is not consistent with the new value of the PurchaseOrderHeader.SubTotal column.
CREATE TABLE purchaseorderheader(
purchaseorderid NUMBER(4),
revisionnumber NUMBER(2),
status NUMBER(1),
employeeid NUMBER(3),
vendorid NUMBER(4),
shipmethodid NUMBER(1),
orderdate TIMESTAMP,
shipdate TIMESTAMP,
subtotal FLOAT(10),
taxamt FLOAT(10),
freight FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderid)
);
CREATE TABLE purchaseorderdetail(
purchaseorderid NUMBER(4),
purchaseorderdetailid NUMBER(4),
duedate TIMESTAMP,
orderqty NUMBER(6),
productid NUMBER(6),
unitprice FLOAT(10),
receivedqty FLOAT(10),
rejectedqty FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderdetailid),
CONSTRAINT fk_orderid FOREIGN KEY (purchaseorderid) REFERENCES purchaseorderheader(purchaseorderid)
);
What I have come up with so far, any help?
CREATE OR REPLACE TRIGGER Header_Before_Subtotal BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
BEGIN
IF(:NEW.subtotal <> (SELECT unitprice*orderqty FROM purchaseorderdetail GROUP BY purchaseorderid)) THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;
Compute total separately (and reference the master key), and then compare that value to new subtotal.
CREATE OR REPLACE TRIGGER Header_Before_Subtotal
BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
DECLARE
l_total number;
BEGIN
SELECT d.unitprice * d.orderqty
INTO l_total
FROM purchaseorderdetail d
WHERE d.purchaseorderid = :new.purchaseorderid;
IF :NEW.subtotal <> l_total THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;
/

In Oracle, how do I get a list of unique sites where they have been sampled for X number of years?

In Oracle, how do I get a list of unique sites where they have been sampled for X number of years AND have at least one data point every year? We need this to determine which sites to use for a long term trend analysis. I have been able to select a list of distinct sites where the first sample occurred over 36 years ago, but not sure how I would go about making sure each year had at least one data point. I have a feeling doing a COUNT over year might be a way to do this, but not sure of the exact language to get this done.
Here's the sample table (which contains the first data points of my larger dataset). The data for these continue until today.
drop table site_trends;
create table site_trends
(
site_id VARCHAR(30),
date_time DATE,
ANC VARCHAR(30)
);
insert into site_trends values('DR01', (TO_DATE('11/2/1979', 'mm/dd/yyyy')), 20.77);
insert into site_trends values('WR02', (TO_DATE('11/2/1979', 'mm/dd/yyyy')), 40.97);
insert into site_trends values('DR01', (TO_DATE('11/26/1980', 'mm/dd/yyyy')), 10.67);
insert into site_trends values('WR02', (TO_DATE('11/26/1980', 'mm/dd/yyyy')), 43.5);
insert into site_trends values('DR01', (TO_DATE('11/28/1981', 'mm/dd/yyyy')), 45.1);
insert into site_trends values('WR02', (TO_DATE('11/28/1981', 'mm/dd/yyyy')), 22.87);
Here's the code that adds the difference in years from today's date from the date sampled of any sites that were sampled 39+ years ago. I would use a DISTINCT(site_id) to provide me a list of just site_id's, but this shows a bit of how it works. Now I just need to make a condition that requires each year to have one data point per site.
SELECT * FROM
(SELECT site_id, date_time, ANC,
TO_CHAR(current_timestamp, 'yyyy') - TO_CHAR(date_time, 'yyyy') AS diff_year
FROM site_trends)
WHERE diff_year > 38
;
There's probably a bunch of ways to do it. I'd just group by site_id and year and do a count.
select * from (
select site_id,
extract(year from sysdate) - extract(year from date_time) as diff_year,
count(1) as num_years
from site_trends
group by site_id, extract(year from date_time)
) where diff_year > 38 and num_years = diff_year;

Can't figure out cursor for loop in a plsql procedure

I am trying to write a procedure in plsql that takes in two parameters, month and year. The procedure generates data for a table - loanreport. The procedure generates for all loan types in the loan type table. When the procedure is run it should populate the table with:
Month
Year
closed loan amount (sum of loan amounts of loans with status = 6) if no loans have status = 6 then closed loan amount is 0.
4.Average Closing Period
Here are the pertinent tables:
CREATE TABLE LOANDETAILS
(LOANNO VARCHAR2(11) primary key,
PROPERTYID VARCHAR2(10),
CUSTID CHAR(8),
LOANTYPE VARCHAR2(20),
LOANSTATUSCODE NUMBER(3,0),
LOANAMOUNT NUMBER(10,2),
RATE NUMBER(5,2),
LOANCREATIONDATE DATE,
LOANSTATUSDATE DATE,
constraint loandet_prop_fk foreign key(PROPERTYID) references PROPERTIES(propertyid),
constraint loandet_cust_fk foreign key(CUSTID) references customers(custid),
constraint loandet_lt_fk foreign key (LOANTYPE) references loantypes(loantype)
);
--insert
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
CREATE TABLE LOANTYPES
(ltID char(5) constraint loantypes_pk primary key,
loantype VARCHAR2(20) constraint loantypes_lt_unique UNIQUE,
description VARCHAR2(100),
active char(1) constraint loantypes_active CHECK (active IN ('Y','N')) -- if loan type is currently being offered
);
Insert into loantypes values ('LT001', 'VA', 'Service members, veterans or eligible family','Y');
Insert into loantypes values ('LT002', 'FHA', 'Federal Housing Administration eligible loans', 'Y');
Insert into loantypes values ('LT003', 'Conventional', 'Standard loan','Y');
Insert into loantypes values ('LT004', 'Employee', 'Eligible employees of the organization','Y');
Insert into loantypes values ('LT005', 'Reconstruct', 'Relief work reconstruction','N');
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
constraint loantr_pk PRIMARY KEY (LOANTYPE, RMONTH, RYEAR)
);
I am new to sql and I clearly have some knowledge gaps. I am attempting to create a procedure then would like to make a cursor and iterate over the cursor with a for loop to create the desired report. Here is my incomplete code:
CREATE OR REPLACE PROCEDURE loan_type_report_procedure (Month loantypereport.month%type, Year loantypereport.year%type) AS
CURSOR C1 IS
SELECT l.loantype,
loanamount,
loancreationdate,
loanstatusdate,
loanstatuscode,
to_char(LOANCREATIONDATE, 'mm') AS rMonth,
to_char(LOANCREATIONDATE, 'YYYY') AS rYEAR
FROM LOANTYPES l
JOIN LOANDETAILS d
ON l.loantype = d.loantype
WHERE Month = to_char(LOANCREATIONDATE, 'mm')
AND Year = to_char(LOANCREATIONDATE, 'YYYY')
BEGIN
FOR loan_rec in C1 LOOP
As far as my understanding goes for loop goes row by row in the cursor. If I want a final table loan type report that contains loantype, month, year, closed loan amount, and average closing period - how do I make that work? Closed loan amount and average closing period are both aggregated on the loan type grouping. Would I use a group by and having in the cursor select statement?
Thank you for your insight
If I understand your question correctly, you'd like to summarize the number of loans by their LOANTYPE, for each month, and for the loans that were closed (LOANSTATUSCODE = 6), you'd like to SUM their amount and record an AVERAGE of their loan time span.
From the look of LOANTYPEREPORT, it looks like you are planning for this average span to be in a number of days.
To accomplish this, you do not need to use PL/SQL. This can be done with traditional SQL. I'm only guessing at what criteria go into deciding a loan's duration, so I'll outline an example below with a couple variations.
In this example, I needed to modify your tables a little, since they reference other tables not included in your post (I dropped LOANDET_PROP_FK and LOANDET_CUST_FK).
After creating your example tables, create the LOANTYPEREPORT table (modified slightly from your example to compile):
CREATE TABLE LOANTYPEREPORT
(LOANTYPE VARCHAR2(20),
MONTH NUMBER(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2),
CONSTRAINT LOANTR_PK PRIMARY KEY (LOANTYPE, MONTH, YEAR)
);
Also, I added a little extra data for some FHA and Conventional loans, to help differentiate the SUMs and durations in the examples below.
Insert into LOANDETAILS values ('L1000000001','P1000001','C1000001','Conventional',1,87975,9,to_date('26-JUL-2016','DD-MON-YY'),to_date('02-AUG-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000009','P1000009','C1000009','FHA',6,160055,4.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000010','P1000010','C1000010','VA',2,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000011','P1000010','C1000010','VA',6,217600,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('07-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000012','P1000010','C1000010','VA',6,111111,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('17-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000013','P1000010','C1000010','VA',2,222222,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-DEC-2016','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000014','P1000010','C1000010','Conventional',6,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-JAN-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000015','P1000010','C1000010','Conventional',5,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-FEB-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000016','P1000010','C1000010','Conventional',4,333333,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000017','P1000010','C1000010','FHA',4,444444,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000018','P1000010','C1000010','FHA',6,200000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-APR-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000019','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('27-MAY-2017','DD-MON-YYYY'));
Insert into LOANDETAILS values ('L1000000020','P1000010','C1000010','FHA',6,300000,7.5,to_date('30-NOV-2016','DD-MON-YYYY'),to_date('22-MAY-2017','DD-MON-YYYY'));
Then, you can load the report table.
Example 1 This assumes that only closed loans should be included in the loan-duration average, that the loan-duration is between LOANCREATIONDATE and LOANSTATUSDATE, and that you only want data for months and loan-types where loans were actually closed. This means july 2016 will not be included at all, since no loans were closed in that month.
INSERT INTO LOANTYPEREPORT
SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE);
Then see what it did:
SELECT YEAR,MONTH,LOANTYPE,CLOSEDLOANSAMOUNT,AVERAGECLOSINGPERIOD
FROM LOANTYPEREPORT
ORDER BY YEAR, MONTH, LOANTYPE;
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 12 FHA 160055 7
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 4 FHA 200000 148
2017 5 FHA 600000 175.5
Example 2: But if you want to include data for months where no loans were closed for a given loan-type (I'm not sure but this might be the third item in your post), then you'll need to enumerate the months.
You can do this several ways, but I'll just include an extra query in this example that sets boundaries for the for 2016 - 2018.
Run the insert:
INSERT INTO LOANTYPEREPORT
WITH YEAR_MONTH AS(
SELECT THE_MONTH.MONTH_NUMBER,
THE_YEAR.YEAR_NUMBER
FROM
(SELECT LEVEL AS MONTH_NUMBER FROM DUAL CONNECT BY LEVEL < 13) THE_MONTH
CROSS JOIN
(SELECT YEAR_NUMBER FROM
(SELECT LEVEL AS YEAR_NUMBER FROM DUAL CONNECT BY LEVEL < 2019)
WHERE YEAR_NUMBER BETWEEN 2016 AND 2018) THE_YEAR
)
SELECT
LOANTYPES.LOANTYPE,
YEAR_MONTH.MONTH_NUMBER,
YEAR_MONTH.YEAR_NUMBER,
SUM(COALESCE(CLOSED_LOAN.LOANAMOUNT,0)) AS CLOSED_LOAN_AMOUNT,
AVG(CLOSED_LOAN.LOAN_DURATION) AS AVERAGE_LOAN_DURATION
FROM
YEAR_MONTH
CROSS JOIN LOANTYPES
LEFT OUTER JOIN (SELECT EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS YEAR,
LOANDETAILS.LOANTYPE,
LOANDETAILS.LOANAMOUNT,
LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE AS LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6) CLOSED_LOAN
ON YEAR_MONTH.YEAR_NUMBER = CLOSED_LOAN.YEAR
AND YEAR_MONTH.MONTH_NUMBER = CLOSED_LOAN.MONTH
AND LOANTYPES.LOANTYPE = CLOSED_LOAN.LOANTYPE
GROUP BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE
ORDER BY YEAR_NUMBER, MONTH_NUMBER, LOANTYPES.LOANTYPE;
And see what data is generated:
YEAR MONTH LOANTYPE CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
2016 1 Conventional 0
2016 1 Employee 0
2016 1 FHA 0
2016 1 Reconstruct 0
2016 1 VA 0
2016 2 Conventional 0
...
...
...
2016 12 Conventional 0
2016 12 Employee 0
2016 12 FHA 160055 7
2016 12 Reconstruct 0
2016 12 VA 328711 12
2017 1 Conventional 333333 58
2017 1 Employee 0
2017 1 FHA 0
2017 4 FHA 200000 148
2017 4 Reconstruct 0
2017 4 VA 0
2017 5 Conventional 0
2017 5 Employee 0
2017 5 FHA 600000 175.5
2017 5 Reconstruct 0
2017 5 VA 0
2017 6 Conventional 0
2017 6 Employee 0
2017 6 FHA 0
This way you get sum of closing amounts for loans closed each month of each type, or zero if none were closed.
EDIT with an example of returning from a function.
Just to reiterate, you do not need to use a function to do this kind of reporting.
But if you have a requirement to use a function, here is an example:
First, create your return type:
CREATE TYPE LOAN_TYPE_MONTH_REPORT IS OBJECT (
LOANTYPE VARCHAR2(20),
MONTH number(2,0),
YEAR NUMBER(4,0),
CLOSEDLOANSAMOUNT NUMBER(15,2),
AVERAGECLOSINGPERIOD NUMBER(5,2)
);
/
CREATE TYPE LOAN_TYPE_MONTH_REPORT_LIST IS TABLE OF LOAN_TYPE_MONTH_REPORT;
/
Then create your function:
CREATE FUNCTION GET_LOAN_TYPE_REPORT_FOR_MONTH(P_YEAR IN NUMBER, P_MONTH IN NUMBER)
RETURN LOAN_TYPE_MONTH_REPORT_LIST
IS
V_MONTH_REPORT LOAN_TYPE_MONTH_REPORT_LIST;
BEGIN
SELECT
LOAN_TYPE_MONTH_REPORT(
THE_MONTH_YEAR.LOANTYPE,
THE_MONTH_YEAR.THE_MONTH,
THE_MONTH_YEAR.THE_YEAR,
COALESCE(CLOSED_LOAN_SUMMARY.CLOSED_LOAN_AMOUNT,0),
CLOSED_LOAN_SUMMARY.AVERAGE_LOAN_DURATION)
BULK COLLECT INTO V_MONTH_REPORT
FROM
(SELECT P_YEAR AS THE_YEAR, P_MONTH AS THE_MONTH, LOANTYPES.LOANTYPE FROM LOANTYPES) THE_MONTH_YEAR
LEFT OUTER JOIN
(SELECT
LOANDETAILS.LOANTYPE,
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE) AS THE_MONTH,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE) AS THE_YEAR,
SUM(LOANDETAILS.LOANAMOUNT) AS CLOSED_LOAN_AMOUNT,
AVG(LOANDETAILS.LOANSTATUSDATE - LOANDETAILS.LOANCREATIONDATE) AS AVERAGE_LOAN_DURATION
FROM LOANDETAILS
WHERE LOANDETAILS.LOANSTATUSCODE = 6
GROUP BY
LOANDETAILS.LOANTYPE,
EXTRACT(YEAR FROM LOANDETAILS.LOANSTATUSDATE),
EXTRACT(MONTH FROM LOANDETAILS.LOANSTATUSDATE)) CLOSED_LOAN_SUMMARY
ON THE_MONTH_YEAR.THE_YEAR = CLOSED_LOAN_SUMMARY.THE_YEAR
AND THE_MONTH_YEAR.THE_MONTH = CLOSED_LOAN_SUMMARY.THE_MONTH
AND THE_MONTH_YEAR.LOANTYPE = CLOSED_LOAN_SUMMARY.LOANTYPE;
RETURN V_MONTH_REPORT;
END;
/
Then test it:
Here's a month with two loan-types with closings:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2016,12));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 12 2016 0
VA 12 2016 328711 12
Reconstruct 12 2016 0
FHA 12 2016 160055 7
Conventional 12 2016 0
Or a month with just one loan-type with a closing:
SELECT * FROM TABLE(GET_LOAN_TYPE_REPORT_FOR_MONTH(2017,01));
LOANTYPE MONTH YEAR CLOSEDLOANSAMOUNT AVERAGECLOSINGPERIOD
Employee 1 2017 0
Reconstruct 1 2017 0
FHA 1 2017 0
VA 1 2017 0
Conventional 1 2017 333333 58

Date difference between first and last book per each author

I would create this table.
create table Books
(
book_id number PRIMARY KEY,
Title number,
yearpub DATE,
author_id number
)
create table Authors
(
author_id number,
book_id number
)
create table Author_name
(
author_id number,
first_name varchar(10),
last_name varchar(10)
)
I have no Oracle installed now but I wanna select
Date difference (number of years) between first and last book per each author.
I think there should be some aggregate function.
SELECT authors.author_id,
max(name.first_name||' '||name.last_name) as full_name,
max(to_char(yearpub,'yyyy')) - min(to_char(yearpub,'yyyy')) as years
from author_name name, books,authors
where
authors.author_id = name.author_id and
authors.author_id = books.author_id and
authors.book_id = books.book_id
group by authors.author_id

sql query help me with correct update statement [duplicate]

This question already has an answer here:
Update query resulting wrongly
(1 answer)
Closed 8 years ago.
I have table name emp with 3 columns empid, datof birth, doj
There is an another table test, it has 2 columns empid date of birth. The employee id is the same in both tables.
My requirement is in emp table for some employees in dateofbirth (dob) column who is haveing date '01/05/2011' has to be updated by the dob in table 2 (test)
I need a update statement.
I have joined the query I got some records now I need to replace employees dob in table1 with date dob of same employee from table 2 (test)
Oracle does not support JOIN query directly with UPDATE Statement...
A workaround would be like this:
UPDATE
(SELECT emp.dob AS emp_dob, test.dob AS test_dob
FROM emp
INNER JOIN test
ON emp.empid = test.empid
) tbl
SET tbl.emp_dob = tbl.test_dob

Resources