I've been asked to provide a list of all employees who are scheduled to take >6 trips. I need to have all the columns of their record showing for each trip.
I'm very new to SQL and don't have the logic down. So far I've been able to get a count:
SELECT SURNAME, GIVEN_NAME, COUNT(SURNAME)
from EP_EVENT
GROUP BY SURNAME, GIVEN_NAME HAVING COUNT(SURNAME) > 6;
But I need to see * not just SURNAME and GIVEN_NAME, none of the other columns contain the same information.
Help
You could use windowed COUNT:
WITH cte AS (
SELECT e.*, COUNT(*) OVER (PARTITION BY SURNAME, GIVEN_NAME) AS cnt
FROM EP_EVENT e
)
SELECT *
FROM cte
WHERE cnt > 6;
Related
I have an employee table as below. As you can see that second highest salary is 200
Incase the second highest salary is missing then there will be only one row as shown at last . In this case the query should fetch only 100
I have written query as but it is not working. Please help! Thanks
select salary "SecondHighestSalary" from(
(select id,salary,rank() over(order by salary desc) rnk
from employee2)
)a
where (rnk) in coalesce(2,1)
I have also tried the following but it is fetching 2 rows but i need only 1
It sounds like you'd want something like
with ranked_emp as (
select e.*,
rank() over (order by e.sal desc) rnk,
count(*) over () cnt
from employee2 e
)
select salary "SecondHighestSalary"
from ranked_emp
where (rnk = 2 and cnt > 1)
or (rnk = 1 and cnt = 1)
Note that I'm still using rank since you're using that in your approach and you don't specify how you want to handle ties. If there are two employees with the same top salary, rank will assign both a rnk of 1 and no employee would have a rnk of 2 so the query wouldn't return any data. dense_rank would ensure that there was at least one employee with a rnk of 2 if there were employees with at least 2 different salaries. If there are two employees with the same top salary, row_number would arbitrarily assign one the rnk of 2. The query I posted isn't trying to handle those duplicate situations because you haven't outlined exactly how you'd want it to behave in each instance.
If you are in Oracle 12.2 or higher, you can try:
select distinct id,
nvl
(
nth_value(salary, 2) from first
over(partition by id
order by salary desc
range between unbounded preceding and unbounded
following),
salary
) second_max_salary
from employee2
So I have two tables salary and emp whose definition is shown as below
[
I am tring to create a query that Find the employee who draws the maximum salary and Display the employee details along with the nationality.
I created this query
select empcode,
max(basic) as "Highest Sal"
from salary
join emp on empcode;
Please help with this
Your query uses a simple aggregate max(basic) which would find the highest salary. Except you need to join to the EMP table to display other details. This means you can't use aggregation, because we need to GROUP BY the non-aggregated columns, which would make a nonsense of the query.
Fortunately we can solve the problem with an analytic function. The subquery selects all the relevant information and ranks each employee by salary, with a rank of 1 being the highest paid. We use rank() here because that will handle ties: two employees with the same basic will be in the same rank.
select empcode
, empname
, nationality
, "Highest Sal"
from (
select emp.empcode
, emp.empname
, emp.nationality
, salary.basic as "Highest Sal"
, rank() over (order by salary.basic desc ) as rnk
from salary join emp on emp.empcode = salary.empcode
)
where rnk = 1;
Find the employee who draws the maximum salary
An employee can have multiple salaries in your datamodel. An employee's (total) salary hence is the sum of these. You want to find the maximum salary per employee and show the employee(s) earning that much.
You can use MAX OVER to find the maximum sum:
select e.*, s.total_salary
from emp e
join
(
select
empcode,
sum(basic) as total_salary,
max(sum(basic)) over () as max_total_salary
from salary
) s on s.empcode = e.empcode and s.total_salary = s.max_total_salary
order by e.empcode;
Try this:
SELECT * FROM
(SELECT E.EmpCode, E.EmpName, E.DOB, E.DOJ, E.DeptCode, E.DesgCode, E.PhNo,
E.Qualification, E.Nationality, S.Basic, S.HRA, S.TA, S.UTA, S.OTRate
FROM EMP AS E JOIN SALARY AS S ON (E.EmpCode = S.EmpCode) order by S.Basic desc)
WHERE rownum = 1
Consider a database schema with three relations:
Employee (*eid:integer*, ename:string, age:integer, salary:real)
Works (*eid:integer*, *did:integer*, pct_time:integer)
Department(*did:integer*, dname:string, budget:real, managerid:integer)
Query the view above to find the name of the manager who manages most employees. If thesame employee works in several departments, that employee is counted once in each of the
departments. The manager is included in the count the same as all other employees, i.e., based
on his or her records in the Works table.
Why do I get this error:
ORDER BY SUM (EmpCount) DESC)
*
ERROR at line 6:
ORA-00907: missing right parenthesis
Here is my query:
SELECT distinct(MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrID
FROM ManagerSummary
GROUP BY MgrID
ORDER BY SUM (EmpCount) DESC
LIMIT 1 );
The view is:
CREATE VIEW ManagerSummary (DeptName, MgrID, MgrName, MgrSalary, EmpCount)
AS SELECT d.dname, d.managerid, e.ename, e.salary,
(SELECT COUNT (w.did)
FROM works w
WHERE w.did = d.did
GROUP BY w.did)
FROM employee e, department d WHERE d.managerid = e.eid;
Thank you
Update: Changing LIMIT 1 for WHERE ROWNUM = 1 doesn't help
Try this
SELECT DISTINCT (MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrId
FROM ( SELECT MgrId, SUM (empcount) AS maxemp
FROM ManagerSummary
GROUP BY MgrId
ORDER BY SUM (empcount) DESC)
WHERE ROWNUM = 1)
You seem to want the name of the manager that has the most employees.
My guess is that you can do this in Oracle as:
select ms.MgrName
from (select ms.*
from ManagerSummary ms
order by EmpCount desc
) ms
where rownum = 1;
It is hard for me to envision a table called ManagerSummary that would have more than one row per MgrId. That's why I don't think aggregation is necessary.
SELECT mgrname
FROM (SELECT mgrname, numemps
FROM (SELECT mgrname, count(*) numemps
FROM mgrsummary
GROUP BY mgrname)
ORDER BY NUMEMPS desc);
Just noticed - this is based on a view. This is ~not~ going to perform well.
i want to delete the last recent record from my table.
Code to select the last record:
SELECT * FROM
( select ID, NAME,
createdon
from Person where age= 30
order by createdon DESC)
WHERE ROWNUM <= 1;
i tried this to delete the last records:
DELETE * FROM
( select ID, NAME,
createdon
from Person where age= 30
order by createdon DESC)
WHERE ROWNUM <= 1;
It 's not working.
ERROR: "invalid table name"
Any help please, Thank you
As OracleUser said, you can't delete from an in-line view. You can use your original inner query to delete based on all three columns it selects, assuming they will uniquely identify a single row:
delete from person
where (id, name, createdon) = (
select * from (
select id, name, createdon
from person
where age = 30
order by createdon desc
)
where rownum <= 1
);
SQL Fiddle.
If ID is a primary or unique key you can do this instead:
delete from person
where id =
(
select id
from (
select id, row_number() over (order by createdon desc) as rn
from person where age = 30
)
where rn = 1
);
If it is not then you can use rowid instead, replacing both references to id in the statement.
The innermost query is basically the same as the inner query in your select, but I'm using the row_number analytic function to assign the equivalent of rownum. The next layer out filters out everything except the most recent, based on the row_number calculation.
You can use rank() instead but could get two record with exactly the same times, and would need to decide whether both should be deleted, or if you should have some additional way to break the tie - e.g. order by createdon desc, id desc. As I've shown it here, row_number() also breaks the tie arbitrarily but can have the explicitly extra ordering to control that, as would rownum. And there's also dense_rank().
SQL Fiddle.
This is a bit simpler but would also delete multiple rows, if you had more than one with the same createdon value:
delete from person
where createdon =
(
select max(createdon)
from person
where age = 30
);
I have table that stores employee job name, it has the following columns:
id; date_from; date_to; emp_id; jobname_id; grade;
Each emp_id can have many consecutive records with the same jobname_id due to many grade changes.
How can I select previous different jobname_id omitting those that are the same like the most current one?
This solution uses the FIRST_VALUE() analytic function to identify each employee's current job. It then filters for all the jobs which dfon't match that one:
select distinct id
, jobname_id
from ( select id
, jobname_id
, first_value(jobname_id) over (partition by id
order by from_date desc) as current_job
from employee
where emp_id = 1234 )
where jobname_id != current_job
order by id, jobname_id
/
Will this work for your issue:
SELECT DISTINCT
e1.emp_id,
e1.jobname_id
FROM employee e1
WHERE NOT EXISTS
(SELECT 1
FROM employee e2
WHERE e1.emp_id = e2.emp_id
AND SYSDATE BETWEEN e2.date_from
AND NVL(e2.date_to, SYSDATE + 1));
(This asumes your table is named "employee" and emp_id is the PK value).
It selects unique emp_id, jobname_id values where the emp_id, jobname_id values are not current.
EDIT: I agree with Chin Boon that fundamentally this is a design issue and perhaps that should be addressed rather than working around the problem.