How to tune query to fetch result faster | Oracle 19c | - sql

I have a table which as huge records in table
My tables : employee and customer
Now the issue here is I have 2 billion records in employee table and 1 billion records in customer table
Employee columns
empid
empname
empage
empdcourse
Customer columns
custid
custdesc
custmessage
My query :
select emp_id from employee where empid not in ( select custid from customer);
Error : It throws me table space issue. Not allowed to increase table space
Is their any way I can tune my query or run in batch by batch so I get output
Any solution is much appreciated !!!
Need it on high priority

NOT EXISTS may be more efficient and less memory consuming in such case.
(The query suggests Customer and Employee share the same PK, does it mean you have an "super" table Person ?)

Try this:
with tmp as
(select /*+full(c)*/
custid
from customer c)
select /*+full(e)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;
The hint full will prevent the tablespace issue.
The OUTER JOIN is faster than the NOT IN.
You can improve it by adding the hint parallel, starting with a degree=2 or 4 like this:
with tmp as
(select /*+full(c) parallel(c,2)*/
custid
from customer c)
select /*+full(e) parallel(e,2)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;

You can add indexes for columns, for example, if they aren’t primary keys:
CREATE INDEX empid_index
ON employee(empid);
Also, you can update the query:
select e.empid from employee e where not exists (select 1 from customer c where c.custid = e.empid);

Related

How this query is returning me 1100 value if there is no salary against the foreign key 30

Write a query to get the minimum salary of department number 30,
the salary should add commission
select *
from emp
select *
from dept
select min(sal+comm) as 'sal+com'
from emp
where deptno = 3
select min(sal+comm) as 'sal+comm'
from emp, dept
where dept.deptno = 30
This is the question and the queries I tried they both are giving me different outputs but how its giving 1100 if there is no foreign key of 30 in emp table.
Your query has basically said for every row in emp select every row in dept and filter the results where dept has a dept no of 30. Even though you have a foreign key you still have to specify the join in the select. The FL is more about referential integrity.
Try
select min(sal+comm) as "sal+comm"
from emp inner join dept
on dept.deptno=emp.deptno
where dept.deptno=30
However because you have null in the commission column sal+comm might equal null. So use min(isnull(sal,0) + isnull(comm,0))
And finally you don't actually need the dept table as you are querying on a value that is already in the emp table so
select min(isnull(sal,0)+isnull(comm,0)) as "sal+comm"
from emp
where deptno=30
In your query, you're select from two tables, but you haven't specified a criterion to join the two tables. This result in a cross join, that means you have a cartesian product of First table tuples with second tables tuples.
You can try adding a clause where you say "and emp.deptno = dept.deptno"

SQL JOIN to get the compare two values/row from table "A" and the same row from table "B"

I have two tables with the following rows
Table A (transaction)
Order Seller Customer
1 300 500
Table B (Persons)
PersonID FullName
300 Peter White
500 Scott Bold
I want a result like this
Order Seller Customer FullName (Seller) FullName (customer)
1 300 500 Peter White Scott Bold
I've tried multiple things however which makes more sense is a join a table twice, however I'm getting:
Ambiguous column name
This is SQL Server 2019.
Basically I'm looking to retrieve info from the same table instead of creating additional tables. Is that possible? If yes, how do you do? Thank you in advance.
As #jarlh wrote in comment:
select t.order, t.seller, t.customer, sel.fullname, cust.fullname
from transaction t
join persons sel -- sel is an alias to persons table
on sel.personid = t.seller
join persons cust
on cust.personid = t.customer;
Query with join will return the result as long as both seller and customer exist in persons table -- here it should as source table names transactions :).
I have another form of query it still join table B twice.
This is archaic syntax which I don't recommend but for beginner know the concept of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A,B where A.Seller=B.PersionID
) t, B where t.Customer=B.PersionID
The proper way of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A JOIN B ON A.Seller=B.PersionID
) t JOIN B ON t.Customer=B.PersionID
Hoping this can help you.

How to create this append record?

I have a table full with employees structured as:
tblEmployees
+--------------+------------+-----------+-------+
| EmployeeID | FirstName | LastName | Wage |
+--------------+------------+-----------+-------+
I then have a table which the user can paste data into from an external software which looks like so:
tblImport
+------------+-----------+--------------+
| EmployeeID | WorkDate | HoursWorked |
+------------+-----------+--------------+
This will then go into another table (HoursWorkedRecords) which is structured the same way.
When I append from the import table to the main table what I would like is firstly:
The append to check if the EmployeeID pasted into the tblImport table exists in tblEmployees, if so then it append to HoursWorkedRecords.
Before importing check there are no duplicate records by the EmployeeID on that given WorkDate.
My question is how can I achieve this?
You can use a query to do this. If you use a LEFT JOIN between HoursWorkedRecords and tblEmployees on EmployeeID then any null entries in your employees table will signify hours worked records where the employee could not be found. You can either use this query directly or through a VBA module.
The (untested) SQL for the query is
SELECT
HWR.EmployeeID
FROM HoursWorkedRecords AS HWR
JOIN tblEmployees AS TE
ON HWR.EmployeeID = TE.EmployeeID
WHERE
TE.EmployeeID IS NULL
The answer to your question depends on how you wish to proceed should either of your requirements fail to be met:
What should happen if the EmployeeID is not found in the tblEmployees table?
What should happen if there are duplicates found in the HoursWorkedRecords table?
If the answer to these questions is to simply ignore the records which do not meet the criteria, then this can be achieved with a relatively simply INSERT query:
insert into hoursworkedrecords
select
i.employeeid, i.workdate, i.hoursworked
from
(tblimport i inner join tblemployees e on i.employeeid = e.employeeid)
left join hoursworkedrecords h on i.employeeid = h.employeeid and i.workdate = h.workdate
where
h.employeeid is null
Here, the inner join on the tblEmployees table ensures that the EmployeeID is valid, and the left join on the hoursworkedrecords table in conjunction with the is null criteria ensures that a record for that employee on that date does not exist.
If however, the user should be alerted to these issues, you should use the reverse of the above query to select the invalid records for the user to review before proceeding.

Query to combine data from 2 tables based on a condition for both the tables in SQL

I have 2 tables. ProfileInfo (ProfileID - PK) and EmployeeRole (EmpID - PK, ProfileID - FK). Both are connected using a ProfileID and both tables have LastUpdatedTimestamp Column. I need to fetch data from both the tables combined, using from and to lastupdated timestamp.
Sometimes both the tables get updated at the same time and most times
only one get updated
. Here is what i have tried but it bring up data which is updated on both tables. Firstly, I tried join but it didn't work as much as i thought it would
select emp.emp_id as EmpId from EmployeeRole emp
FULL OUTER JOIN ProfileInfo pi on emp.profile_id = pi.profile_id
where emp.LST_UPDT_TS between '2017-09-18' and '2017-09-20' and
pi.LST_UPDT_TS between '2017-09-18' and '2017-09-20';
This brought emp ids that had changes on both the tables alone.
Table Details:
EmployeeRole Emp_ID PK, Profile_id FK, LST_UPDT_TS TIMESTAMP
ProfileInfo Profile_Id PK, Profile_name, LST_UPDT_TS TIMESTAMP
Example: If 2 records of ProfileInfo gets updated and 1 record of EmployeeRole gets updated. I need to get 3 emp_id considering both the records from ProfileInfo is not related to EmployeeRole record. If in case one of the record is related then I have to get 2 emp_id only.
I searched for similar answers for a short period but nothing worked. Please help.
This is just an example, your conditions may vary
SELECT
-- common data
COALESCE(emp.profile_id, pi.profile_id) as profile_id
,COALESCE(emp.LST_UPDT_TS, pi.LST_UPDT_TS) as LST_UPDT_TS
-- emp role
,emp.emp_id as EmpId
-- profile
, pi.Profile_name
FROM (SELECT *
FROM EmployeeRole
WHERE LST_UPDT_TS between '2017-09-18' and '2017-09-20') emp
FULL OUTER JOIN (
SELECT *
FROM ProfileInfo
WHERE LST_UPDT_TS between '2017-09-18' and '2017-09-20') pi
-- rows matching predicate
ON emp.profile_id = pi.profile_id
AND emp.LST_UPDT_TS = pi.LST_UPDT_TS
This worked with some little tweeks from the initial query I changed.
select emp.emp_id as EmpId from EmployeeRole emp
JOIN ProfileInfo pi on emp.profile_id = pi.profile_id and
((emp.LST_UPDT_TS between '2017-09-18' and '2017-09-20') or
(pi.LST_UPDT_TS between '2017-09-18' and '2017-09-20'));
Thanks a lot #Serg and #Phil and #wildplasser

How to create an sql command that has SELECT statements from 2 different tables?

How to create an sql command that has SELECT statements from 2 different tables? For example,
select ID from EMP_details, select job_id from Jobs_details
So how can i possibly merge both into one
Selecting from two or more tables When rows in them tables has some sort of relation so you want to extract the corresponding row you would use a JOIN something like this ....
JOIN
SELECT EMP.ID, JD.job_id
FROM EMP_details EMP INNER JOIN jobs_details JD
ON EMP.CommonColumn = JD.CommonColumn
Results From Two SELECTS
When you have two SELECT statements and just want to get the results returned from them queries into one row you can do something like this ...
SELECT X.A , Y.B
FROM (select ID AS A from EMP_details) X, (select job_id AS B from Jobs_details) Y
This is known as a JOIN in SQL. Your query might look like this:
SELECT EMP_details.ID,
EMP_details.Name,
Job_details.RefNumber
FROM EMP_details,
Jobs_details
WHERE EMP_details.ID = Jobs_details.job_id;
Having a column in both tables by which you can match the rows from the first table to the second one, like for example the job_id in Jobs_details matches job_id in Emp_details, you could do:
SELECT e.ID,j.job_id
FROM EMP_details e
INNER JOIN jobs_details j ON e.job_id = j.job_id
For more information on JOIN's see the documentation.
Have you try
SELECT id FROM (SELECT id FROM EMP_details UNION ALL SELECT id FROM Jobs_details) as temp_table;
Thanks,