Get oldest date in database SQL [duplicate] - sql

This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
Closed 12 months ago.
select
max((date '2019-07-01' - applicant.applicantbirthdate) / 365 as age,
applicant.applicantfirstname,
applicant.applicantlastname,
office.officename
from
applicant
inner join
office on office.officeid = applicant.officeid
group by
applicant.applicantfirstname, applicant.applicantlastname,
office.officename;
I'm not really sure what to do here. I'm suppose to pick the oldest user and list their office. but this shows the oldest user for all offices. how can I just only show the oldest person out of all the offices

This example is based on Scott's sample schema whose tables simulate what you have.
SQL> SELECT ename, hiredate
2 FROM emp
3 ORDER BY hiredate DESC;
ENAME HIREDATE
---------- ----------
ADAMS 12.01.1983 --> Adams has the MAX hiredate; you want his data
SCOTT 09.12.1982
MILLER 23.01.1982
FORD 03.12.1981
JAMES 03.12.1981
KING 17.11.1981
MARTIN 28.09.1981
TURNER 08.09.1981
CLARK 09.06.1981
BLAKE 01.05.1981
JONES 02.04.1981
WARD 22.02.1981
ALLEN 20.02.1981
SMITH 17.12.1980
14 rows selected.
Using a CTE which includes the RANK analytic function that "sorts" rows by hiredate in descending order (so that people - who have the MAX hiredate - rank as "highest")), in final query you just fetch those whose rank = 1:
SQL> WITH
2 temp
3 AS
4 (SELECT e.ename,
5 d.dname,
6 e.hiredate,
7 RANK () OVER (ORDER BY e.hiredate DESC) rn
8 FROM emp e JOIN dept d ON e.deptno = d.deptno)
9 SELECT ename, dname, ROUND ((SYSDATE - hiredate) / 365) age
10 FROM temp
11 WHERE rn = 1;
ENAME DNAME AGE
---------- -------------- ----------
ADAMS RESEARCH 39
SQL>
Applied to your query:
WITH
temp
AS
(SELECT a.applicantfirstname,
a.applicantlastname,
o.officename,
a.birthdate,
RANK () OVER (ORDER BY a.birthdate DESC) rn
FROM applicant a JOIN office o ON o.officeid = a.officeid)
SELECT applicantfirstname,
applicantlastname,
officename,
ROUND ((SYSDATE - birthdate) / 365) AS age
FROM temp
WHERE rn = 1;

#The below code should work. I recommend to go with RANK over if its large dataset but if its small dataset the below code works fine as well.
select applicant.applicantfirstname, applicant.applicantlastname, office.officename, max((date '2019-07-01' - applicant.applicantbirthdate) / 365 as age
FROM
applicant
INNER JOIN office ON office.officeid = applicant.officeid
WHERE
applicant.applicantbirthdate IN (
SELECT MIN(applicant.applicantbirthdate) FROM applicant);

Try the below one. There are two things missing in your query.
We should list them based on descending order. So putting ORDER BY age DESC would ensure it.
We need to get the oldest candidate in terms of age. So LIMIT 1 would ensure that we would get only one record.
select (date '2019-07-01' - applicant.applicantbirthdate)/365 as age, applicant.applicantfirstname, applicant.applicantlastname, office.officename
from applicant
inner join office on office.officeid = applicant.officeid
group by applicant.applicantfirstname, applicant.applicantlastname, office.officename
order by age desc
limit 1;

Related

why can't I use grouping functions without group by?

In the following code, why can't I use count () for each row in the table? The count() must return the number of colours of each row, which all become one, but it does not. If I use group by, it will.
select colour,count(*)
from bricks;
updated:
another example:
select b.*,
(select count(*) from bricks where colour=b.colour)
from bricks b;
The above example used grouping function without group by and it works without any errors
That's just the way SQL demands it. You can't select a discrete column and and aggregate function without listing the discrete columns in a group by statement.
Your second example runs a subquery for each record returned from the main bricks query. This won't perform as well as the first query using a group by.
And you best alias your subquery table - I've seen circumstances where the parser decides you're essentially saying b.colour = b.colour, which will give you the same count(*) for each record in bricks.
I don't have those bricks, but - I do have Scott's sample EMP table with jobs instead.
This is what you tried (and it doesn't work):
SQL> select job, count(*)
2 from emp
3 order by 1, 2;
select job, count(*)
*
ERROR at line 1:
ORA-00937: not a single-group group function
This is what works, but - that's not what you want:
SQL> select job, count(*)
2 from emp
3 group by job
4 order by 1, 2;
JOB COUNT(*)
--------- ----------
ANALYST 2
CLERK 4
MANAGER 3
PRESIDENT 1
SALESMAN 4
This is what you want (and it works), but - doesn't look pretty:
SQL> select e.job,
2 (select count(*) from emp a where a.job = e.job) cnt
3 from emp e
4 order by 1, 2;
JOB CNT
--------- ----------
ANALYST 2
ANALYST 2
CLERK 4
CLERK 4
CLERK 4
CLERK 4
MANAGER 3
MANAGER 3
MANAGER 3
PRESIDENT 1
SALESMAN 4
SALESMAN 4
SALESMAN 4
SALESMAN 4
14 rows selected.
Good news for you - use count function in its analytic form:
SQL> select job, count(*) over (partition by job order by null) cnt
2 from emp
3 order by 1, 2;
JOB CNT
--------- ----------
ANALYST 2
ANALYST 2
CLERK 4
CLERK 4
CLERK 4
CLERK 4
MANAGER 3
MANAGER 3
MANAGER 3
PRESIDENT 1
SALESMAN 4
SALESMAN 4
SALESMAN 4
SALESMAN 4
14 rows selected.
SQL>

How to fix group function nested too deeply error

I've run into an error I've never seen before while trying to learn SQL where it is saying that my group by function is nested too deeply? Any ideas on how to fix this code would be greatly appreciated. I am trying to find the division with the most employees.
Tables:
division(DID, dname, managerID)
employee(empid, name, salary, DID)
Code:
select dname
from division
where did in (select did from employee group by did having max(count(empid)))
I don't have your tables, but Scott's sample schema contains similar tables - dept (departments) and emp (employees who work in these departments).
How many employees work in each department?
SQL> select deptno, count(*)
2 from emp
3 group by deptno
4 order by 2 desc;
DEPTNO COUNT(*)
---------- ----------
30 6 --> this is what you want, it has the most employees
20 5
10 3
Which department is it?
SQL> select * from dept order by deptno;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO --> it's SALES
40 OPERATIONS BOSTON
SQL>
This is what you tried: not that it won't work (Oracle doesn't let you), syntax is wrong. having clause should be something like having count(*) = 25, not just your wishes comes true (having max(count(*)) which reads as "give me department that has maximum count of employees").
SQL> select dname
2 from dept
3 where deptno in (select deptno from emp
4 group by deptno
5 having max(count(empno))
6 );
having max(count(empno))
*
ERROR at line 5:
ORA-00935: group function is nested too deeply
SQL>
So, what can we do about it? A simple option is to rank departments by number of employees:
SQL> select deptno,
2 count(*) cnt,
3 rank() over (order by count(*) desc) rnk
4 from emp
5 group by deptno;
DEPTNO CNT RNK
---------- ---------- ----------
30 6 1 --> department 30 ranks as the highest
20 5 2
10 3 3
SQL>
The rest is easy: use that query as a subquery (or a CTE, as I did), and select the one that ranks the highest:
SQL> with temp as
2 (select deptno,
3 count(*) cnt,
4 rank() over (order by count(*) desc) rnk
5 from emp
6 group by deptno
7 )
8 select d.dname
9 from dept d join temp t on t.deptno = d.deptno
10 where t.rnk = 1; --> the highest rank
DNAME
--------------
SALES
SQL>
SALES it is.

How can i write hired the same month employees and order?

Sql, which gives the number of employees hired in the same month (or year) grouped and sequentially on date basis.
I tried to write this code, but i didn't find same hired and order.
SELECT hire_date,COUNT(hire_date)
FROM employees
GROUP BY hire_date;
This is how I understood the question.
Sample data:
SQL> select ename, hiredate from emp order by hiredate;
ENAME HIREDATE
---------- ----------
SMITH 17_12_1980
ALLEN 20_02_1981
WARD 22_02_1981
JONES 02_04_1981
BLAKE 01_05_1981
CLARK 09_06_1981
TURNER 08_09_1981
MARTIN 28_09_1981
KING 17_11_1981
JAMES 03_12_1981
FORD 03_12_1981
MILLER 23_01_1982
SCOTT 09_12_1982
ADAMS 12_01_1983
14 rows selected.
Employed in the same month:
SQL> select to_char(hiredate, 'mm.yyyy') hire_month,
2 count(*)
3 from emp
4 group by to_char(hiredate, 'mm.yyyy')
5 order by 1;
HIRE_MO COUNT(*)
------- ----------
01.1982 1
01.1983 1
02.1981 2
04.1981 1
05.1981 1
06.1981 1
09.1981 2
11.1981 1
12.1980 1
12.1981 2
12.1982 1
11 rows selected.
SQL>
Hired in the same year:
SQL> select extract(year from hiredate) hire_year,
2 count(*)
3 from emp
4 group by extract(year from hiredate)
5 order by 1;
HIRE_YEAR COUNT(*)
---------- ----------
1980 1
1981 10
1982 2
1983 1
SQL>

Unable to MAX(COUNT) and have multiple columns

I have 4 tables, EMPLOYEE, DRIVER, TRIP and TRIPLEG
EMPLOYEE table has Name which I want to extract and show with MAX count, has E# which is shared with DRIVER
DRIVER table has L#(licence number) which is common with TRIP
TRIP table has T#(trip number) which is common with TRIPLEG
I'm trying to find the max number of tripleg a driver has done(In this case driver with licence number 10002:
SELECT MAX(COUNT(TRIPLEG.LEG#))
FROM TRIP, TRIPLEG
ON TRIP.T# = TRIPLEG.T#
WHERE TRIP.L# = 10002
GROUP BY TRIP.T#
COUNT(TRIPLEG.LEG#) gives me https://i.imgur.com/AYAovov.png,
so I did the above MAX(COUNT(TRIPLEG.LEG#)) which gives me this: https://i.imgur.com/alCFlO3.png
I'm unable to proceed as I tried SELECTING more columns(TRIP.T#) like
SELECT TRIP.T#, MAX(COUNT(TRIPLEG.LEG#))
FROM TRIP, TRIPLEG
ON TRIP.T# = TRIPLEG.T#
WHERE TRIP.L# = 10002
GROUP BY TRIP.T#
Gives me an error: ORA-00937: not a single-group group function
Any advice? Need to be able to start small and selecting before I can join more tables to get the Employee name displayed beside the MAX tripleg count
Thanks in advance
Essentially I want something like: (only 1 row, which is the MAX triplegs done (5))
NAME MAX(COUNT(TRIPLEG.LEG#))
-----------------------------------
BOB 5
I don't have your table so I'll use Scott's EMP and DEPT (as you use Oracle, so I presume you're familiar with them).
This works:
SQL> select d.dname, count(e.empno) cnt
2 from emp e join dept d on e.deptno = d.deptno
3 where d.deptno in (10, 20)
4 group by d.dname;
DNAME CNT
-------------- ----------
ACCOUNTING 3
RESEARCH 5 --> MAX count is this
SQL>
Nested count works if there are no other columns in SELECT column list (you already know that), and it returns desired value:
SQL> select max(count(e.empno)) cnt
2 from emp e join dept d on e.deptno = d.deptno
3 where d.deptno in (10, 20)
4 group by d.dname;
CNT
----------
5
SQL>
But, this won't work (you know that too):
select d.dname, max(count(e.empno)) cnt
from emp e join dept d on e.deptno = d.deptno
where d.deptno in (10, 20)
group by d.dname;
To fix it, use CTE (Common Table Expression a.k.a. the WITH factoring clause) or an inline view; I'll show you the first option, with yet another addition: I'll rank counts and find the "highest" one, and use it later to select only desired row.
SQL> with tcnt as
2 (select d.deptno,
3 d.dname,
4 count(e.empno) cnt,
5 rank() over (order by count(e.empno) desc) rnk --> rank them DESC
6 from emp e join dept d on e.deptno = d.deptno
7 where d.deptno in (10, 20)
8 group by d.dname, d.deptno
9 )
10 select t.deptno, t.dname, t.cnt
11 from tcnt t
12 where rnk = 1; --> fetch only row(s) with highest rank
DEPTNO DNAME CNT
---------- -------------- ----------
20 RESEARCH 5
SQL>
Finally, add some more columns from other tables:
SQL> with tcnt as
2 (select d.deptno,
3 d.dname,
4 count(e.empno) cnt,
5 rank() over (order by count(e.empno) desc) rnk
6 from emp e join dept d on e.deptno = d.deptno
7 where d.deptno in (10, 20)
8 group by d.dname, d.deptno
9 )
10 select t.deptno, t.dname, t.cnt, e.ename, e.job
11 from tcnt t join emp e on e.deptno = t.deptno
12 where rnk = 1;
DEPTNO DNAME CNT ENAME JOB
---------- -------------- ---------- ---------- ---------
20 RESEARCH 5 SMITH CLERK
20 RESEARCH 5 JONES MANAGER
20 RESEARCH 5 SCOTT ANALYST
20 RESEARCH 5 ADAMS CLERK
20 RESEARCH 5 FORD ANALYST
SQL>
Based on your tables to find the max number of tripleg a driver has done(In this case driver with licence number 10002:
Select a.tripno, max(a.trips)
From
(Select Trip.T# as tripno, count(tripleg.leg#) as trips
From tripleg join trip on tripleg.T# = trip.T#
where trip.L# = 10002
Group by tripno
) a
Group by a.tripno

ORDER BY with DISTINCT gives ORA-01791: not a SELECTed expression

I trying to use oracle order by with select statement but it causes an Exception:
ORA-01791: not a SELECTed expression.
select distinct usermenu.menuname
from usermenu, userpermission
where userpermission.menuno = usermenu.menuno
and userpermission.userno = 1
order by userpermission.menuno;
When there's DISTINCT or an aggregate function in the SELECT statement's column list, ORDER BY a column which isn't part of the SELECT column list won't work.
Here's an example, based on Scott's schema.
This works OK, although D.LOC isn't selected:
SQL> select d.dname, e.ename
2 from dept d join emp e on e.deptno = d.deptno
3 order by d.loc;
DNAME ENAME
-------------- ----------
SALES BLAKE
SALES TURNER
SALES ALLEN
SALES MARTIN
SALES WARD
SALES JAMES
RESEARCH SCOTT
RESEARCH JONES
RESEARCH SMITH
RESEARCH ADAMS
RESEARCH FORD
ACCOUNTING KING
ACCOUNTING MILLER
ACCOUNTING CLARK
14 rows selected.
Now, add DISTINCT - basically, that's what you have:
SQL> select distinct d.dname, e.ename
2 from dept d join emp e on e.deptno = d.deptno
3 order by d.loc;
order by d.loc
*
ERROR at line 3:
ORA-01791: not a SELECTed expression
The same goes for aggregate functions, such as COUNT:
SQL> select d.dname, e.ename, count(*)
2 from dept d join emp e on e.deptno = d.deptno
3 group by d.dname, e.ename
4 order by d.loc;
order by d.loc
*
ERROR at line 4:
ORA-00979: not a GROUP BY expression
SQL>
So, what to do? Order by something else. Alternatively, use the current query as an inline view, join it with the table that contains the column you'd want to order the result by and it'll work:
SQL> select x.dname, x.ename
2 from (select distinct d.dname, e.ename
3 from dept d join emp e on e.deptno = d.deptno
4 ) x
5 join dept d1 on d1.dname = x.dname
6 order by d1.loc;
DNAME ENAME
-------------- ----------
SALES TURNER
SALES JAMES
SALES BLAKE
SALES WARD
SALES MARTIN
SALES ALLEN
RESEARCH SMITH
RESEARCH FORD
RESEARCH ADAMS
RESEARCH SCOTT
RESEARCH JONES
ACCOUNTING MILLER
ACCOUNTING KING
ACCOUNTING CLARK
14 rows selected.
SQL>