ORA-00904: "DAYS": invalid identifier - sql

Here is the code that I have:
SELECT (first_name || ' ' || last_name) AS Name, hire_date, days FROM EMPLOYEES WHERE days > 365*6;
This is what I am supposed to do:
Create a SQL query that shows the first_name, last_name, hire_date, and the number of days that the employee has worked from the EMPLOYEES table. Use the concatenation operator to put the first_name and the last_name together in the same column in the result set with a space between the two names. Use date arithmetic to show only employees that have worked longer than 6 years (365 * 6).
Can someone help me figure out what my error is?

To correct your query you need to perform date arithmetic.
SELECT
(first_name || ' ' || last_name) AS name,
hire_date,
ROUND(sysdate - hire_date) AS days
FROM hr.employees
WHERE sysdate - hire_date > 6*365;
But if you analyse -> hr schema, you find out, that there is job_history table relevant for this task. In my opinion correct solution should be like this:
SELECT a1.name,
a1.hire_date,
a1.days
FROM
(SELECT employees.employee_id,
(employees.first_name || ' ' || employees.last_name) AS name,
employees.hire_date,
SUM(NVL(job_history.end_date, TRUNC(sysdate)) - NVL(job_history.start_date, hire_date)) AS days
FROM hr.employees
LEFT JOIN hr.job_history
ON job_history.employee_id = employees.employee_id
GROUP BY employees.employee_id,
(employees.first_name || ' ' || employees.last_name),
employees.hire_date
) a1
WHERE days > 365*6;

You may try to put filter on the hire day instead
WHERE hire_date > sysdate - 365*6

this will work;
WHERE sysdate-hire_date >= 365*6

Related

How can i group data by column that i create for query

How can I group data by "work experience"
SELECT
CONCAT(CONCAT(FIRST_NAME, ' '), LAST_NAME) AS "Name and Ln",
MONTHS_BETWEEN(SYSDATE, hire_date) / 12 AS "work experience"
FROM
HR.EMPLOYEES
WHERE
MONTHS_BETWEEN(SYSDATE, hire_date) >= 15 * 12
How can I group my query by that column work experience that I create? I need to write group by "work experience' or what
Group By clause is not required here.
As the requirements mentioned in the issue, you can use 'distinct' as following:
SELECT distinct(round(MONTHS_BETWEEN(SYSDATE, hire_date) / 12,0)) AS work_experience,
CONCAT(CONCAT(FIRST_NAME, ' '), LAST_NAME) AS Name_and_Ln
FROM HR.EMPLOYEES
WHERE MONTHS_BETWEEN(SYSDATE, hire_date) >= 15 * 12
order by work_experience desc;
If the above code doesn't resolve your issue, please update the required output you need.

Oracle "NOT A GROUP BY EXPRESSION ERROR-00979"

Below is my PL/SQL Oracle code. It prints the year in which max number of employees got hired and also prints the no of employees joined each month in that year.
If I execute the below code without the for-loop part it generates an error:
not a group by function error.
What can be the reason am I missing something obvious?
declare
v_year number(4);
v_c number(2);
begin
select to_char(hire_date,'yyyy') into v_year
from employees
group by to_char(hire_date,'yyyy')
having count(*) =
( select max( count(*))
from employees
group by to_char(hire_date,'yyyy')); // gets the year where max employees joined
dbms_output.put_line('Year : ' || v_year);
for month in 1 .. 12
loop
select count(*) into v_c
from employees
where to_char(hire_date,'mm') = month and to_char(hire_date,'yyyy') = v_year;
dbms_output.put_line('Month : ' || to_char(month) || ' Employees : ' || to_char(v_c));
end loop;
end;
Below is the code without for-loop:
declare
v_year number(4);
v_c number(2);
begin
select to_char(hire_date,'yyyy') into v_year
from employees
group by to_char(hire_date,'yyyy')
having count(*) =
( select max( count(*))
from employees
group by to_char(hire_date,'yyyy'));
dbms_output.put_line('Year : ' || v_year);
end;
It generates the following error:
Error report - ORA-00979: not a GROUP BY expression ORA-06512: at line 6
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
You don't need PL/SQL for this. Also, your SELECT ... INTO will fail if its query returns more than one row, which it would if there were two or more years with the same maximum number of employees hired.
select to_char(hire_date, 'YYYY'), to_char(hire_date, 'MM'), count(*)
from employees
group by rollup(to_char(hire_date, 'YYYY'), to_char(hire_date, 'MM'))
having to_char(hire_date, 'YYYY') =
(select to_char(hire_date, 'YYYY')
from employees
group by to_char(hire_date, 'YYYY')
having count(*) =
(select max(count(*))
from employees
group by to_char(hire_date, 'YYYY')))
order by to_char(hire_date, 'YYYY'), to_char(hire_date, 'MM')
P.S. I get the same error as you when I run your second example (no loop) in SQL Developer, but I do not get an error when I run it in SQL*Plus. SQL*Plus reports only "PL/SQL procedure successfully completed."
I think you'd better to rewrite the code using concurrent loops with year for the outer and month for the inner one through use of arrays such as
DECLARE
v_year OWA.nc_arr;
v_month OWA.nc_arr;
y INT := 0;
m INT := 0;
BEGIN
FOR yr IN
(
SELECT hire_year
FROM( SELECT TO_CHAR(hire_date, 'yyyy') AS hire_year,
DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS dr
FROM employees
GROUP BY TO_CHAR(hire_date, 'yyyy'))
WHERE dr = 1
)
LOOP
y := y + 1;
v_year(y) := yr.hire_year;
DBMS_OUTPUT.PUT_LINE('Year'||y||' : ' || v_year(y));
FOR m IN 1 .. 12
LOOP
SELECT COUNT(*)
INTO v_month(m)
FROM employees
WHERE TO_NUMBER(TO_CHAR(hire_date, 'yyyy'))=v_year(y)
AND TO_NUMBER(TO_CHAR(hire_date, 'mm'))= m;
DBMS_OUTPUT.PUT_LINE('Month : ' || m || ' Employees : ' || to_char(v_month(m)));
END LOOP;
END LOOP;
END;
/
where analytic function is used for the year loop, since there might be more than one year, and multiple(12) variables will be needed for the month loop per each year.

How to find out the exact age of employees as years and months

I have a employee table with DOB column so, now I want to display all employees current age.
To find out the age I knew the query as below
SELECT *
FROM (SELECT ename,
job,
dob,
TRUNC(MONTHS_BETWEEN(SYSDATE,DOB)/12,1) AGE
FROM employee);
by using this query I can get all employees age but my requirement is, if a employee age is displayed as 2.5 then I need to display that age as 2 years 6 months.
Try this ---
SELECT ename,
job,
dob, --TRUNC(MONTHS_BETWEEN(SYSDATE, DOB) / 12, 1) AGE
trunc(months_between(sysdate, DOB) / 12) || ' years ' ||
trunc(mod(months_between(sysdate, DOB), 12)) || ' months ' AGE
FROM employee;

Query- SQL Developer

I have a question that says Write a SELECT statement to get a list of employees hired in the period from July 1998 to December 1999 . The list must contain the employee id the last and first name and the monthly salary – given that the table contains the yearly salary and that employees get 12 salaries per year.
I wrote this,but does not work:
SELECT FIRST_NAME, LAST_NAME, EMPLOYEE_ID, SALARY/12 as MONTHLY_SALARY
FROM HR.EMPLOYEES
WHERE HIRE_DATE BETWEEN JULY-1998 AND DECEMBER-1999 ;
Could be you have a wrong date format (for mysql)
SELECT FIRST_NAME, LAST_NAME, EMPLOYEE_ID, SALARY/12 as MONTHLY_SALARY
FROM HR.EMPLOYEES
WHERE HIRE_DATE BETWEEN STR_TO_DATE('07-01-1998, '%m-%d-%Y)
AND STR_TO_DATE('12-31-1999, '%m-%d-%Y) D ;
For sqlserver
SELECT FIRST_NAME, LAST_NAME, EMPLOYEE_ID, SALARY/12 as MONTHLY_SALARY
FROM HR.EMPLOYEES
WHERE HIRE_DATE BETWEEN Cast('07-01-1998'as datetime)
AND Cast('12-31-1999' as datetime) ;
And for ORACLE
SELECT FIRST_NAME, LAST_NAME, EMPLOYEE_ID, SALARY/12 as MONTHLY_SALARY
FROM HR.EMPLOYEES
WHERE HIRE_DATE BETWEEN TO_DATE('07-01-1998' , 'MM-DD-YYYY')
AND TO_DATE('12-31-1999' , 'MM-DD-YYYY') ;

Find hire date difference between two employees

I have an employee table where the fields are:
first_name, last_name, hire_date, salary, department_id, department_name, and so on.
I intend to find the hire date difference between EMPLOYEE1 and EMPLOYEE2, then EMPLOYEE2 and EMPLOYEE3, and so on.
I have to write a query in sql to display the first name and hire date difference of employee
We can use DATEDIFF to calculate the date difference.
e.g
SELECT DATEDIFF(SELECT DATE_ADD(start_date,INTERVAL 1 DAY),end_date);
hope it will help you
also there is also way of using to_days function. click here for more detail
Since you've still not mentioned what RDBMS you are using i'll start with SQL-Server:
WITH x
AS (SELECT first_name,
last_name,
hire_date,
salary,
department_id,
department_name,
hireNum=Row_number()
OVER(
ORDER BY hire_date)
FROM dbo.employee)
SELECT DiffDays=Datediff(day, x.hire_date, x2.hire_date),
first_name,
last_name,
hire_date,
salary,
department_id,
department_name
FROM x
INNER JOIN x x2
ON x.hirenum = x2.hirenum + 1
To find the difference between dates in Microsoft SQL 2012 using days (substitute day with year, hour, etc.):
Select datediff(day, HireDate, EndDate)
From Employee1