I know how to use cumulative sum in its basic formulation, with code like this:
Table Name: Employees
dept_id salary
-------------
10 1000
10 1000
10 2000
10 3000
20 5000
20 6000
20 NULL
SELECT dept_id,
salary,
SUM(salary) OVER(PARTITION BY dept_id
ORDER BY salary ASC
rows unbounded preceding) cum_sum
FROM Employees;
dept_id salary cum_sum
--------------------------
10 1000 1000
10 1000 2000
10 2000 4000
10 3000 7000
20 5000 5000
20 6000 11000
20 NULL 11000
But how do I limit the cumulative sum to only N preceding rows?
For example, limit cumulative sum to current row and previous two rows.
dept_id salary cum_sum
--------------------------
10 1000 1000
10 1000 2000
10 2000 4000
10 3000 6000
20 5000 5000
20 6000 11000
20 NULL 11000
The SQL syntax is:
SELECT dept_id,
salary,
SUM(salary) OVER(PARTITION BY dept_id
ORDER BY salary ASC
rows between <N> preceding and current row) cum_sum
FROM Employees;
Related
-- Created table
CREATE TABLE EMPLOYEE(NAME VARCHAR(15),GENDER VARCHAR(10),SALARY INT);
-- Inserted values
INSERT INTO EMPLOYEE VALUES
('AJAY','M',1000),('SURYA','M',3000),('RITHU','F',4000),('KARTHIK','M',2000),('SAMANTHA','F',10000),('MSD','M',10000);
-- Cumulative Window Function
SELECT
NAME,
GENDER,
SALARY,
AVG(SALARY) OVER(ORDER BY SALARY ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS AVG_SAL,
COUNT(SALARY) OVER(ORDER BY SALARY ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS COUNT_SAL,
SUM(SALARY) OVER(ORDER BY SALARY ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS SUM_SAL
FROM
EMPLOYEE
ORDER BY
SALARY;
-- Answer for my query
The rows which I marked in the answer image(1,2)(10000,20000) should be (2,1)(20000,10000)
As stated in the comments, since both Salaries are equal, you will need to define another column in the ORDER BY in order to get further order:
E.g.
ORDER BY SALARY, COUNT_SAL DESC
or
ORDER BY SALARY, SUM_SAL DESC
Both of them will give the following output:
NAME GENDER SALARY AVG_SAL COUNT_SAL SUM_SAL
-------- ------ ------ ------- --------- -------
AJAY M 1000 5000 6 30000
KARTHIK M 2000 5800 5 29000
SURYA M 3000 6750 4 27000
RITHU F 4000 8000 3 24000
MSD M 10000 10000 2 20000
SAMANTHA F 10000 10000 1 10000
Bear in mind that this will work in the example, but may not work with more duplicate salaries. You will need to find different columns to apply this logic.
This question already has answers here:
What is the difference between count(0), count(1).. and count(*) in mySQL/SQL?
(9 answers)
Closed 3 years ago.
I use oracle 11g. I want maximum and minimum salary, and count of employees for each department, so I do this :
select d.department_id, d.department_name, max(salary), min(salary), count(*)
from employees e ,
departments d
where e.department_id = d.department_id
group by d.department_id, d.department_name;
and it works :
DEPARTMENT_ID DEPARTMENT_NAME MAX(SALARY) MIN(SALARY) COUNT(*)
------------- ------------------------------ ----------- ----------- ----------
100 Finance 12008 6900 6
50 Shipping 8200 2100 45
70 Public Relations 10000 10000 1
30 Purchasing 11000 2500 6
90 Executive 24000 17000 3
10 Administration 4400 4400 1
110 Accounting 12008 8300 2
40 Human Resources 6500 6500 1
20 Marketing 13000 6000 2
60 IT 9000 4200 5
80 Sales 14000 6100 34
11 rows selected.
So what does count(*) mean? Count departments or what ?
count(*) returns the rows that match the where statement.
In your case its where e.department_id=d.department_id.
Because you applied a group by your count(*) will return the count of rows for each group (d.department_id).
This means you will get the count of employees (e.department_id) for each department (d.department_id).
This question already has answers here:
Select second most minimum value in Oracle
(3 answers)
Closed 4 years ago.
EMPID NAME DEPTID SALARY
---------- ------------------------------------------ --
101 surendra 201 1000
102 narendra 202 2000
103 rajesh 203 3000
104 ramesh 203 2000
105 hanumanth 202 10000
a) Write a Query to find least 5th (Least salary in 5th position from
least salary in the order) salaried employee?
b) Query to find the highest earning employee in each department
a) Write a Query to find least 5th (Least salary in 5th position from least salary in the order) salaried employee?
SELECT EMPID,NAME,DEPTID,SALARY
FROM
(
SELECT EMPID,NAME,DEPTID,SALARY, DENSE_RANK() OVER (ORDER BY SALARY) AS RN
FROM Table1
)
WHERE RN=5
b) Query to find the highest earning employee in each department
SELECT EMPID,NAME,DEPTID,SALARY
FROM
(
SELECT EMPID,NAME,DEPTID,SALARY,
DENSE_RANK() OVER (PARTITION BY DEPTID ORDER BY SALARY DESC) AS RN
FROM Table1
)
WHERE RN=1
Demo
http://sqlfiddle.com/#!4/63ce0/12
Let's assume we have a table named EmployeeSalary which has 3 columns:
Id
Name
Salary
Salary might be same for multiple employee according to the following table data
Id Name Salary
----------
6 Belalo 74
1 Karim 100
5 dIPU 100
4 Satter 102
9 Kiron 120
10 Rash 120
11 Harun 130
13 Baki 130
12 Munshi 132
2 Rahim 500
7 Kaif 987
8 Sony 987
3 Belal 4000
Now the query will be
SELECT A.Salary
FROM
(
SELECT DISTINCT Salary,
DENSE_RANK() OVER (ORDER BY Salary) AS Ranks
FROM [dbo].[EmployeeSalary]
) A
WHERE A.Ranks=5
I have the following table with data:
ID SAL
_______________
1 1500
1 1500
1 2000
1 1500
2 2500
2 2500
3 1500
I want to query the same data BUT with new column that gives me a sequence of each duplicated row (based on id and sal columns).
My desired query results should be like this:
ID SAL ROW_SEQ
_______________________
1 1500 1
1 1500 2
1 2000 1
1 1500 3
2 2500 1
2 2500 2
3 1500 1
Any one has any idea PLEASE!..
You want to use a ROW_NUMBER() function here.
SELECT ID, SAL, ROW_NUMBER() OVER (PARTITION BY ID, SAL, ORDER BY SAL) AS ROW_SEQ
FROM MyTable
ORDER BY ID, SAL
By partitioning over your two desired fields, it will give you a ranking within each group in a sequential manner.
The documentation on it can be found here:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm
I have table like this:
name | salary
Tom | 10000
Mary | 20000
Jack | 30000
Lisa | 40000
Jake | 60000
I need an update query to update the salary column depending on the values it contains.
Salaries need to increase by:
5000 for values between 10000 to 15000
7000 for values between 15000 to 20000
8000 for values between 20000 to 30000
10000 for values between 40000 to 60000
Try using the CASE statement within the UPDATE command
UPDATE
[yourtablename]
SET
salary =
CASE
WHEN salary BETWEEN 10000 AND 15000 THEN salary + 5000
WHEN salary BETWEEN 15000 AND 20000 THEN salary + 7000
WHEN salary BETWEEN 20000 AND 30000 THEN salary + 8000
WHEN salary BETWEEN 40000 AND 60000 THEN salary + 10000
ELSE salary
END
Something like this:
UPDATE YourTable
SET salary = CASE
WHEN salary > 10000 AND salary <= 15000 THEN salary + 5000
WHEN salary > 15000 AND salary <=20000 THEN salary + 7000
.
.
.
END
Just use an UPDATE statement with a CASE statement with the required logic in it:
UPDATE SalaryTable
SET Salary =
(CASE WHEN Salary BETWEEN 10000 AND 14999 THEN Salary + 5000
WHEN Salary BETWEEN 15000 AND 19999 THEN Salary + 7000
WHEN Salary BETWEEN 20000 AND 29999 THEN Salary + 8000
WHEN Salary BETWEEN 40000 AND 59000 THEN Salary + 10000
ELSE Salary
END)
I've used BETWEEN which evaluates greater than or equal to and less than or equal to, hence the values like 14999.
Also, you have a gap between 30000 and 40000, which isn't picked up, but I'm assuming this is down to it being dummy data.
Reference:
SQL BETWEEN
SQL CASE
This should work:
UPDATE T
SET T.Salary += CASE
WHEN T.salary BETWEEN 10000 AND 15000 THEN 5000
WHEN T.salary BETWEEN 15000 AND 20000 THEN 7000
WHEN T.salary BETWEEN 20000 AND 30000 THEN 80000
WHEN T.salary BETWEEN 40000 AND 60000 THEN 10000
ELSE 0
END
FROM YourTable AS T