SELECT
CONCAT(CONCAT(FIRST_NAME, ' '), LAST_NAME) AS "Fn and Ln",
JOB_ID AS "Job_title",
CASE COMMISSION_PCT
WHEN NULL THEN SALARY
WHEN '-' THEN SALARY
ELSE (COMISSION_PCT * SALARY) * 12
END AS "Year income"
FROM HR.EMPLOYEES
I have to find year income of employee considering premium. If there is no premium i have to just ignore it. In my code i get 'ORA-00904: "COMISSION_PCT": invalid identifier' i dont know what is the reason. Dtype of COMISSION_PCT NUMBER(2,2) and SALARY dtype is NUMBER(8,2).
Clarification:
Specify the amount of annual income of each employee, given that the bonus is indicated as a percentage
Your syntax is a bit off.
Try this as your CASE statement:
CASE
WHEN COMMISSION_PCT IS NULL THEN SALARY
WHEN COMMISSION_PCT = '-' THEN SALARY
ELSE (COMMISSION_PCT * SALARY)
END * 12 AS "Year income"
The immediate problem is that you have a typo; as the error says you refer to COMISSION_PCT, when the column is called COMMISSION_PCT with two Ms.
ELSE (COMMISSION_PCT * SALARY) * 12
Then, your case expression is comparing with string literal '-', but as the column is numeric no rows can have that value, so you get "ORA-00932: inconsistent datatypes: expected NUMBER got CHAR". It appears your client is displaying null values as dashes. So you don't need to handle those.
CASE COMMISSION_PCT
WHEN NULL THEN SALARY
ELSE (COMMISSION_PCT * SALARY) * 12
END AS "Year income"
Although that form of case expression is valid - there are two forms - in this situation you need a searched expression (as #Vvdl said!) because a simple one can't compare with null (as nothing is equal to, or not equal to, null):
CASE
WHEN COMMISSION_PCT IS NULL THEN SALARY
ELSE (COMMISSION_PCT * SALARY) * 12
END AS "Year income"
Though even that might not get the result you want. If salary is monthly then you need to multiply by 12 in both cases, or at the end:
CASE
WHEN COMMISSION_PCT IS NULL THEN SALARY
ELSE (COMMISSION_PCT * SALARY)
END * 12 AS "Year income"
fiddle
Related
I have a simple table
create table employees (empno int primary key, empname varchar(30),
emailaddress varchar(30), phonenumber varchar(10))
EMPNO EMPNAME EMAILADDRESS PHONENUMBER
1 Emma emma#gmail.com 82354566
2 Tom tom#gmail.com 984537665
3 Bob Bob#gmail.com
I want to show the results such as if phone number for a particular customer is not blank, then make his email address as blank else display the email address as it is.
My desired result should be
EMPNO EMPNAME EMAILADDRESS PHONENUMBER
1 Emma 82354566
2 Tom 984537665
3 Bob Bob#gmail.com
It should display blank and should not display not null.
I tried the following
select *
case
when phonenumber is not null
then '' as emailaddress
end
from employees
but it says ORA-00923: FROM keyword not found where expected
Here is my demo - DB Fiddle
Change to:
select empno, empname, phonenumber,
case
when phonenumber is not null
then ''
else emailaddress
end as emailaddress
from employees
DBFIDDLE
As xQbert said, your case construct is wrong, but you are also missing a comma between * and your case expression, and if you combine * with anything else then it has to be prefixed with the table name or alias.
So you could do:
select e.*,
case when phonenumber is not null then null else emailaddress end as etc
from employees e
Or slightly shorter (relying on a missing else evaluating to null anyway):
select e.*,
case when phonenumber is null then emailaddress end as etc
from employees e
Or to not show the email address at all if there is a phone number:
select
empno,
empname,
case when phonenumber is null then emailaddress end as emailaddress,
phonenumber
from employees
EMPNO
EMPNAME
EMAILADDRESS
PHONENUMBER
1
Emma
null
82354566
2
Tom
null
984537665
3
Bob
Bob#gmail.com
null
Or if you only want to show one or the other as a single column:
select
empno,
empname,
case when phonenumber is null then emailaddress else phonenumber end as etc
from employees
Or use coalesce instead of case:
select
empno,
empname,
coalesce(phonenumber, emailaddress) as etc
from employees
EMPNO
EMPNAME
ETC
1
Emma
82354566
2
Tom
984537665
3
Bob
Bob#gmail.com
db<>fiddle
select salary
from (
(select salary
from employees
where rownum<=10
order by salary desc)
minus
(select salary
from employees
where rownum<=4
order by salary desc)
);
You cannot use ORDER BY there.
Try this instead:
select salary from (
select salary, row_number() over ( order by salary desc ) rn
from employees )
where rn between 5 and 10;
On Oracle 12c or later, you can also do this:
select salary from employees
order by salary desc
offset 4 rows fetch next 6 rows only;
You've got several issues in what you've written. The immediate problem is that you'll get an error from having an order by in the first branch of your union, but just removing that won't help you much.
You're making a (fairly common) mistake with ordering and rownum; looking just at the first subquery you have:
select salary
from employees
where rownum<=10
order by salary desc
The rownum filter will be applied before the order-by, so what this will actually produce is 10 indeterminate rows from the table, which are then ordered. If I run that I get:
SALARY
----------
24000
13000
12000
10000
8300
6500
6000
4400
2600
2600
but you'll see different values, even from the same sample schema. If you look at the whole table you'll see higher values than those; and even running the second query will show something isn't as you expect - for me that gets:
SALARY
----------
13000
4400
2600
2600
which are not the first four rows from the previous query. (Again, you'll see different results, but hopefully the same effect; if not, look at the whole table ordered by salary.)
You need to order the whole table - in a subquery - and then filter:
select salary
from (
select salary
from employees
order by salary desc
)
where rownum<=10
which gives a much more sensible - and consistent - result. You can then minus the two queries:
select salary
from (
select salary
from employees
order by salary desc
)
where rownum<=10
minus
select salary
from (
select salary
from employees
order by salary desc
)
where rownum<=4
order by salary desc;
SALARY
----------
13500
13000
12000
11500
You may be expecting to see six values there, but there are three employees with a salary of 12000, and minus eliminates duplicates so that is only reported once. #Matthew's approach (or #Jeff's!) will give you all six, including duplicates, if that is what you want. It also stops you having to hit the table multiple times.
A further problem is with ties - if the 4th highest was the same as the 5th highest, what would you expect to happen? Using minus would exclude that value; #Matthew's approach would preserve it.
You need to define what you actually want to get - the 5th to 10th highest salary values? The salaries of the 5th to 10th highest-paid people (a subtle but important difference)? Do you really only want the numbers, or who those employees are - in which case how you deal with ties is even more important? Etc. Once you know what you actually need to find you can decide the best way to get that result.
It doesn't make sense to order rows in two sets that are subsequently operated upon because sets don't have order. If you need a solution that can execute on older versions and you want to return the bottom 6 ranked out of the top 10 ranked, then this will work. If you can use newer features, then you may want to because it's possible they'll require fewer machine instruction executions.
After making the obvious changes that escaped me in my haste...
select salary
from (
select rownum rn, salary
from (
select salary
from employees
order by salary desc
)
)
where rn between 5 and 10
this code has to sum salary of employees of department_id 100.so it gives this error "missing right parenthesis"
DECLARE
v_department_name VARCHAR(100);
v_department_manager VARCHAR(100);
v_totalsalary NUMBER(30);
BEGIN
SELECT departments.department_name, concat(employees.first_name,
employees.last_name), employees.salary INTO v_department_name,
v_department_manager, v_totalsalary
FROM employees JOIN departments ON employees.department_id =
departments.department_id
WHERE employees.salary = (SELECT departments.department_id,
sum(employees.salary)
FROM EMPLOYEES
where departments.department_id=100
GROUP BY DEPARTMENT_ID
ORDER BY DEPARTMENT_ID);
DBMS_OUTPUT.PUT_LINE ('Department Name is : ' || v_department_name || 'And
Department Manager is : ' || v_department_manager || 'Total Amount of Salary
is : ' || v_totalsalary );
END;
The "missing right parenthesis" error is clearly caused by the ORDER BY clause in the subquery (where it is not allowed).
Once you clear that error, you get the "too many values" error, because you are comparing a single variable (salary) to the output from a subquery that returns two values (department_id AND sum(salary)). Not sure why you thought you need to include the department_id in the SELECT clause of the subquery.
When you include error messages in your question, include the full text of the message (which shows the line number and position at which the error occurred - a crucial detail!)
Take it one small step at a time. Forget for the moment PL/SQL; are you able to write the correct query in SQL, which will return the department name, the manager's name and the sum of the salaries of all the employees in the department? If you can do that, then the PL/SQL around it is easy.
Here is one way to get all the values in one SQL statement:
select d.department_name,
m.first_name || ' ' || m.last_name as manager_name,
sum(e.salary) as sum_salary
from departments d
join
employees m on d.manager_id = m.employee_id
join
employees e on d.department_id = e.department_id
where d.department_id = 100
group by d.department_id, d.department_name, m.first_name, m.last_name
;
DEPARTMENT_NAME MANAGER_NAME SUM_SALARY
--------------- --------------- ----------
Finance Nancy Greenberg 51608
Perhaps 80% of writing good PL/SQL code is simply writing good, efficient SQL statements. If you have any difficulty with this query, you should probably spend the majority of your time writing SQL statements, for the next few days or weeks; return to PL/SQL when you feel this query (in my answer) is "simple", "easy", "standard" (which it is!)
H,
How to use Pattern Matching function in "group By" clause.
Below is the Data
emp_name transaction_id
John 1001
John= 1002
Peter 1003
I want to group by based on emp_name. Here 'John' and 'John=' both are same employee. I want to ignore if the employee name has '=' sign at the end of the column.
Expected Result:
Emp_name countt
John 2
Peter 1
replace works fine and is fast. But since you asked for pattern matching, here is an answer with a pattern:
SELECT regexp_replace(emp_name, '=$', ''), count(*) AS countt
FROM employees
GROUP BY regexp_replace(emp_name, '=$', '');
A simple case statement replacing only the right most = if one exists.
SELECT case when right(emp_name,1) = '=' then left(emp_Name,len(emp_name-1))
else emp_name end as EmpName, count(Transaction_ID) countt
FROM dataTable
GROUP BY case when right(emp_name,1) = '=' then left(emp_Name,len(emp_name-1))
else emp_name end
select
replace (emp_name, '=', '') as emp_name,
count (*) as countt
from employees
group by replace (emp_name, '=', '')
Edit, since you said the name can contain an =
select
case
when emp_name like '%='
then substr (emp_name, 1, length (emp_name) - 1)
else emp_name
end as emp_name,
count (1) as countt
from employees
group by
case
when emp_name like '%='
then substr (emp_name, 1, length (emp_name) - 1)
else emp_name
end
I want to hard-code a column name and its value as New York in a select query with pipe delimiter. E.g. Emp table has columns EmpId, EmpName, Salary. I want output such as
Select EmpId ||'|'||
EmpName ||'|'||
'NewYork' as City ||'|'||
Salary
from Emp
Here I want City column in output query and its value should be 'NewYork' for each record.
Here I am getting error as "FROM keyword not found where expected". When I use comma instead of Pipe Delimiter I am getting result but not with Pipe. Please advise. Thanks in advance.
with emps as (
select 1 as id, 'Smith' as name, 2000 as salary from dual
union
select 2, 'Jones', 2200 from dual
)
select
id || '|' || name as record1,
id || '|' || name || '|NewYork|' || salary as record2,
'NewYork' as city
from emps;