I'm trying to do is write an INSERT statement with three different conditions.
Here is what I have made so far (but this code gets an ORA-00913 too many values error):
INSERT ALL
WHEN SALARY > 20000 THEN
INTO SPECIAL_SAL13(EMPLOYEE_ID,HIRE_DATE,MANAGER_ID,SALARY)
WHEN SALARY <= 20000 THEN
INTO SAL_HISTORY13(EMPLOYEE_ID,SALARY)
WHEN SALARY <= 20000 THEN
INTO MGR_HISTORY13(EMPLOYEE_ID,MANAGER_ID,SALARY)
SELECT EMPLOYEE_ID,HIRE_DATE,MANAGER_ID,SALARY
FROM EMPLOYEES
WHERE EMPLOYEE_ID < 125
try
INSERT ALL
WHEN SALARY > 20000 THEN
INTO SPECIAL_SAL13(EMPLOYEE_ID,HIRE_DATE,MANAGER_ID,SALARY)
VALUES(EMPLOYEE_ID,HIRE_DATE,MANAGER_ID,SALARY)
WHEN SALARY <= 20000 THEN
INTO SAL_HISTORY13(EMPLOYEE_ID,SALARY)
VALUES(EMPLOYEE_ID,SALARY)
WHEN SALARY <= 20000 THEN
INTO MGR_HISTORY13(EMPLOYEE_ID,MANAGER_ID,SALARY)
VALUES(EMPLOYEE_ID,MANAGER_ID,SALARY)
SELECT EMPLOYEE_ID,HIRE_DATE,MANAGER_ID,SALARY
FROM EMPLOYEES
WHERE EMPLOYEE_ID < 125
For reference see here.
Related
I have the table EMPLOYEES with columns EMPLOYEE_ID, NAME, SALARY, COMMISSION_PCT.
I have to calculate the average salary of employees taking into account commissions.
How can I do that? Thank you!
Just like you said:
select avg(sal + nvl(comm, 0)) avg_sal_comm
from emp
If commission part is expressed as percentage, then
select avg(sal + sal * nvl(comm, 0) / 100) avg_sal_comm
from emp;
NVL is here because not all employees have comm column value.
So here is my problem: I need to get batches of rows (select statements) for a migration to another database (other then oracle).
Suggested solution: I take batches of rows (using rowid maybe?) example:
batch1: 0-10000,
batch2: 10000 - 20000,
batchn: 10000(n) - 10000(n+1)
So what should my query be?
batch1: select * from table_name where rownum >= 0 and rownum < 10000,
batch2: select * from table_name where rownum >= 10000 and rownum < 20000,
batch n: select * from table_name where rownum >= 10000*n and rownum < 10000*(n+1)
This does not work, (only the first select will work).
PS, I am pulling this data from a nodejs app, and thus I am sending in these batch queries in a for loop.
To illustrate my comment:
-- Between rows --
SELECT * FROM
( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num
FROM scott.emp
)
WHERE Row_Num BETWEEN 5 and 10
/
You may replace between operator with <= and >= if necessary.
Here's what I see in output:
DEPTNO ENAME SAL ROW_NUM
20 FORD 3000 5
30 JAMES 950 6
20 JONES 2975 7
10 KING 5000 8
30 MARTIN 1250 9
10 MILLER 1300 10
Using rownum is not a great idea, because there's no guarantee that the same rows will be assigned the same rownum values in different queries.
If the table has any combination of columns that uniquely identify a row, it is better to generate a ranking based on that and use that ranking to identify batches of rows. For example:
SELECT * FROM (
SELECT table.*, RANK() OVER (ORDER BY column1, column2) as my_rank
FROM table
)
WHERE my_rank >= 10000 AND my_rank < 20000
This will work with any range, and will be reproducible as long as the values in the columns used do not change and uniquely identify a row. (Actually, I think this would be usable even if they do not uniquely identify a row, as long as they work to break the rows into small enough batches.)
The downside is that MY_RANK will be included in the output. You can avoid that by explicitly listing the columns you do want to select; or it may be easier to filter it out when you are loading the data into the other database.
If you want to preserve the rowids, use the following SQL. This SQL took 4 minutes, 20 seconds to run against a 218 million row table on a 2 CPU server with 18 GB devoted to the DB.
CREATE TABLE rowids
AS
WITH
aset
AS
(SELECT ROWID AS row_id, row_number () OVER (ORDER BY ROWID) r
FROM amiadm.big_table)
SELECT *
FROM aset
WHERE MOD (r, 10000) = 0;
After creating this table, loop through it with the following:
BEGIN
FOR recs
IN ( SELECT row_id
, LAG (row_id) OVER (ORDER BY row_id) prev_row_id
, LEAD (row_id) OVER (ORDER BY row_id) next_row_id
FROM rowids
ORDER BY row_id)
LOOP
IF prev_row_id IS NULL
THEN
SELECT *
FROM big_table
WHERE ROWID <= recs.row_id;
ELSIF next_row_id IS NULL
THEN
SELECT *
FROM big_table
WHERE ROWID > row_id;
ELSE
SELECT *
FROM big_table
WHERE ROWID > prev_row_id
AND ROWID <= row_id;
END IF;
END LOOP;
END;
Create PL / SQL blocks using cursors to update salary columns on employee tables, from employees working in specific departments inputted via keyboard.
Salaries are raised by the rules:
If the employee is less than 16 years old, raise the salary 15%
If the length of employment of employees between 16-20 years, increase salary by 20%
If the employee is over 20 years old, raise salary 25%
Show employee_id, last_name, old job, new salary, on updated employees table.
Enter value for d_id: 30
EMPLOYEE_ID LAST_NAME LAMAKERJA SALARY
----------- ------------------------- ---------- ----------
119 Colmenares 16.1452239 3000
118 Himuro 16.8794705 3120
116 Baida 17.7726212 3480
117 Tobias 18.1917992 3360
115 Khoo 20.3781006 3720
114 Raphaely 20.8219362 13200
6 rows selected.
To get you started: age is a common problem so let's suppose that my trivial calculation does the job. Loop through all employees, check conditions you were told and update employee's salary. The final SELECT is up to you, completely.
FOR cur_r
IN (SELECT employee_id, TRUNC ( (SYSDATE - date_of_birth) / 365.25) age
FROM employees)
LOOP
UPDATE employees e
SET e.salary =
e.salary * CASE
WHEN age ... THEN ...
WHEN age ... THEN ...
END
WHERE e.employee_id = ...
END LOOP;
I have two tables like emp, customer with two salary columns in both tables
emp_sal cusotmer_sal
-------- -------------
1000 3000
2000 1000
3000 5000
I want output combined sum salary in single result like
sum(sal)
---------
15000
could please comment if anyone knows
Thank You!!
You could use a summation of two subqueries, each one calculating the sum of salary:
SELECT
(SELECT SUM(emp_sal) FROM emp) +
(SELECT SUM(customer_sal) FROM customer)
FROM dual
try this
select sum(emp_sal) from emptable
+
select sum(cusotmer_sal) from customertable
Code is written below, multiple nested query:
select *
from
(select employee_id,employee_id
from employees) a
where rownum <= 5
)
where rnum >= 10
If i give duplicate columns in the select its giving "column ambiguously defined" error.
employee_id,employee_id, rownum rnum
Firstly, your query is incorrect since you have ambiguously defined the columns. It will throw ORA-00918: column ambiguously defined.
You must use proper ALIAS to avoid the error. For example,
SELECT departments.department_id AS "dept_id",
employees.department_id AS "emp_Dept_id"
FROM...
Secondly, it is not at all a pagination query. Since you are alwyas going to pick random rows as there is no ORDER BY clause. You are not ordering the rows.
where rownum <= 5
where rnum >= 10
At last, how on earth could you try to fetch the rows beyond 10 when you have fetched ONLY 5 rows in the inner query? It will ALWAYS return zero rows.
The correct way of paging through data is:
SQL> SELECT empno
2 FROM (SELECT empno, rownum AS rnum
3 FROM (SELECT empno
4 FROM emp
5 ORDER BY sal)
6 WHERE rownum <= 8)
7 WHERE rnum >= 5;
EMPNO
----------
7654
7934
7844
7499
SQL>
when you give a.* it means you are trying to refer two columns with same name in a table which is not permitted.The column names in a table are unique
So select employee_id,employee_id from employees is not a problem
but
select a.* from (select employee_id,employee_id from employees)a is a problem
the sqlfiddle here
Also if you want records from 10 to 15 in your query then use like the below
select * from
(select a.*,Rownum rnum from
(select employee_id as emp_id1,employee_id as emp_id2
from employees order by 1)
a where rownum <= 15 ) where rnum >= 10
EDIT1:- If duplicate column is required use like the below
with emp1 as (select employee_id from employees),
emp2 as (select * from
(select a.*,rownum rnum from emp1 a order by 1)
where rownum <=15)
select b.*,c.*
from emp1 b,emp2 c
where b.employee_id=c.employee_id
and c.rnum >=10