i am having a table T1 with some data and it uses a query Q1 to update it initially.Now i am taking the same query Q1 and populating the data in a table T2 every week.T2 is like a temporary table to hold latest data.
The end goal is for T1 to have all the updates from T2 where the FINDING_DATE is updated as per the latest info from T2.
SQL> select * from T1;
ID NAME FINDING_DATE
----- ------------------------------ --------------------
10 vivek 29-12-2022
20 anand 29-12-2022
30 vinod 29-12-2022
40 nandu 29-12-2022
50 sri 29-12-2022
SQL> select * from T2;
ID NAME FINDING_DATE
----- ------------------------------ --------------------
10 vivek 06-01-2023
30 vinod 06-01-2023
40 nandu 06-01-2023
50 sri 06-01-2023
60 nani 06-01-2023
Using the below query i am able to get the new data updated to T1:
insert into T1 select * from T2 where ID in
(select ID from T2
minus
select ID from T1);
SQL> select * from T1;
ID NAME FINDING_DATE
----- ------------------------------ --------------------
10 vivek 29-12-2022
20 anand 29-12-2022
30 vinod 29-12-2022
40 nandu 29-12-2022
50 sri 29-12-2022
60 nani 06-01-2023
Here only a new record is inserted and record with ID=20 is not deleted.Also the FINDING_DATE is not updated.
What is the best way to get the required data updates from T2 to T1.
Here's what I think.
Sample data:
SQL> select * from t1;
ID NAME FINDING_DA
---------- ----- ----------
10 vivek 29-12-2022
20 anand 29-12-2022 --> doesn't have match in T2
30 vinod 29-12-2022
40 nandu 29-12-2022
50 sri 29-12-2022
SQL> select * from t2;
ID NAME FINDING_DA
---------- ----- ----------
10 vivek 06-01-2023
30 vinod 06-01-2023
40 nandu 06-01-2023
50 sri 06-01-2023
60 nani 06-01-2023
99 LF 13-01-2023 --> additional row
Merge will update existing rows and insert missing ones:
SQL> merge into t1
2 using t2
3 on (t1.id = t2.id)
4 when matched then update set t1.finding_date = t2.finding_date
5 when not matched then insert (id, name, finding_date)
6 values (t2.id, t2.name, t2.finding_date);
6 rows merged.
Result: matching rows are updated, new row is added, but non-matching row with ID = 20 wasn't modified in any way:
SQL> select * from t1 order by id;
ID NAME FINDING_DA
---------- ----- ----------
10 vivek 06-01-2023
20 anand 29-12-2022 --> it is still here
30 vinod 06-01-2023
40 nandu 06-01-2023
50 sri 06-01-2023
60 nani 06-01-2023
99 LF 13-01-2023 --> newly added*emphasized text*
7 rows selected.
SQL>
If you want to get rid of rows that don't exist in t2, you'll have to use two statements: one to delete rows, and another to perform update/insert (or merge; that's why it is called upsert).
Deleting rows can be slow; truncate the table instead, as it seems that you don't really care about old values:
SQL> truncate table t1;
Table truncated.
SQL> merge into t1
2 using t2
3 on (t1.id = t2.id)
4 when matched then update set t1.finding_date = t2.finding_date
5 when not matched then insert (id, name, finding_date)
6 values (t2.id, t2.name, t2.finding_date);
6 rows merged.
SQL> select * from t1 order by id;
ID NAME FINDING_DA
---------- ----- ----------
10 vivek 06-01-2023 --> ID = 20 doesn't exist; of course not,
30 vinod 06-01-2023 --> table was truncated
40 nandu 06-01-2023
50 sri 06-01-2023
60 nani 06-01-2023
99 LF 13-01-2023 --> newly added
6 rows selected.
SQL>
Related
Suppose I've next data
id cid vid firstname lastname dtype dname createdat
1 32 34 ramesh kjk t check 2021-11-02 10:00:51.66395
1 32 34 ramesh kjk t check 2021-11-01 10:00:51.66395
1 32 4 raj kjk c check 2021-11-04 10:00:51.66395
excepted o/p:
id cid vid firstname lastname dtype dname createdat
1 32 34 ramesh kjk t check 2021-11-02 10:00:51.66395
1 32 4 raj kjk c check 2021-11-04 10:00:51.66395
need to fetch only the only latest record of each user(vid) and document type can be c or t
use corelated subquery
select t1.* from table_nam t1
where t1.createdat=(select max(createdat) from table_nam t2 where t1.vid=t2.vid)
also you can use distinct on
select distinct on (vid) as vid,createdat,cid
from table_name
order by vid,createdat desc
I need to write a single sql or pl/sql to accomplish the following:
select value1 from table1;
-----------------------------
99
select value2 from table2;
------------------------------
120
I need to find out 99 is what percentage of 120?
Based on the formula P = X1/X2 * 100 the result will be 82.5%
Thanks for your help.
It'll work if both tables have a single row (that's what your examples suggest). I used CTE instead of your "real" tables, so query you might be interested in begins at line #7.
SQL> with
2 table1 (value1) as
3 (select 99 from dual),
4 table2 (value2) as
5 (select 120 from dual)
6 --
7 select a.value1 / b.value2 * 100 as result
8 from table1 a cross join table2 b;
RESULT
----------
82,5
SQL>
As you stated that PL/SQL could be an option, consider creating a function:
SQL> create or replace function f_pct(par_1 in number, par_2 in number)
2 return number
3 is
4 begin
5 return par_1 / par_2 * 100;
6 exception
7 when others then
8 -- in case of e.g. PAR_2 = 0
9 return null;
10 end;
11 /
Function created.
Let's test it:
SQL> select ename, sal, comm, f_pct(comm, sal) result
2 from emp;
ENAME SAL COMM RESULT
---------- ---------- ---------- ----------
SMITH 800
ALLEN 1600 300 18,75
WARD 1250 500 40
JONES 2975
MARTIN 1250 1400 112
BLAKE 2850
<snip>
I have a two table.One of them is student, the other one is salary.
Student table
id | name | code | status
1 | steven | 123 | 100
2 | joe | 678 | 200
3 | paul | 758 | 100
Salary table
id | code | status | currency
1 | 123 | 100 | euro
2 | 678 | 200 | dolar
3 | 758 | 520 | yuan
I want to delete row1 from Student table and row 1 and 2 from Salary table because code and status fields
are same.
I write that query
delete a,b Student as a , join Salary as b
on a.code= b.code and a.status = b.status
but it is not working.I want to delete rows with one query.Do you have any idea?
Would something like this do? PL/SQL, though, not SQL.
Initial data sets:
SQL> select * from student;
ID NAME CODE STATUS
---------- ------ ---------- ----------
1 steven 123 100
2 joe 678 200
3 paul 758 100
SQL> select * from salary;
ID CODE STATUS CURREN
---------- ---------- ---------- ------
1 123 100 euro
2 678 200 dollar
3 758 520 yuan
Remove common (CODE, STATUS) combinations:
SQL> begin
2 for cur_r in (select code, status from student
3 intersect
4 select code, status from salary
5 )
6 loop
7 delete from student where code = cur_r.code and status = cur_r.status;
8 delete from salary where code = cur_r.code and status = cur_r.status;
9 end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
Result:
SQL> select * from student;
ID NAME CODE STATUS
---------- ------ ---------- ----------
3 paul 758 100
SQL> select * from salary;
ID CODE STATUS CURREN
---------- ---------- ---------- ------
3 758 520 yuan
SQL>
You can use two statements to do so easily:
delete student s where exists(
select * from student stu inner join salary sal on stu.code=sal.code and stu.status=sal.status and stu.id=s.id);
delete salary sal where not exists (select code from student stu where stu.code=sal.code);
First one to delete all the students having same code and status in both tables and second is to delete all the rows from salary table where code doesn't exist in student table.
I have below table
userid comp_dd coursecode qualification course_id course passyear totalmarks func stream
----------- ----------- ----------- --------------- ----------- -------------------------------------------------- ----------- -----------------
60 26 1 High School 15 Class 10 26 67 2 All Subject
60 26 2 Senior Secondry 15 Class 12 26 85 2 Commerce
60 2010 3 Graduates 4 B.Tech/B.E 2010 54 1 IT/Computers
60 2013 4 Post Graduates 9 M.com 2013 98.5 2 Commerce
i wanted to get the unique record of max coursecode, the output should be
userid comp_dd coursecode qualification course_id course passyear totalmarks func stream
----------- ----------- ----------- --------------- ----------- -------------------------------------------------- ----------- -----------------
60 2013 4 Post Graduates 9 M.com 2013 98.5 2 Commerce
There will be many records of the different userids
I think you want:
select t.*
from t
where t.coursecode = (select max(t2.coursecode)
from t t2
where t2.userid = t.userid
);
You can also do this with window functions, but the correlated subquery is often faster with the right index, which would be on (userid, coursecode).
Sort the table by coursecode descending and get the 1st row:
select top 1 *
from tablename
order by coursecode desc
This will work only if there are no duplicates in the column coursecode since it will fetch only 1 row, but I guess this is the case because you say:
i wanted to get the unique record of max coursecode
I have two tables and I need to find the person with the highest value.
TABLE1
NAME ID
--------------- ---------------
MIKE 101
MIKE 102
BETTY 103
BETTY 104
BETTY 105
TIM 106
TABLE2
ID VALUE
-------- --------------
101 12
102 10
103 20
104 20
105 10
106 5
I can write a select statement that will give a result of name and values:
SELECT name, value
FROM table1, table2
WHERE table1.id = table.id;
NAME VALUE
----- ----------
MIKE 12
MIKE 10
BETTY 20
BETTY 20
BETTY 10
TIM 5
Now I need to aggregate the values of the rows with equal names and I can not figure it out. Am I going about it the correct way?
Please try this :
select a.name,max(b.value) as value
from table1 a
inner join table2 b on a.id = b.id
group by a.name
Anyway, you tagged mysql and oracle in the question. Luckily, this sql works in both. But you have to remove one of these two tags, to make sure which dbms are you use.
Use this.. and since your column names are unique, you don't need any alias.
select name, max(value) as MaxValue
from table1
inner join table2 on table1.id = table2.id
group by name