Taking the Largest SUM from a table - sql

I'm trying to get the Employee with the highest sales
Employee DeptNo Date Sales
Chris 2 2012/1/1 1000
Joe 1 2012/1/1 900
Arthur 3 2012/1/1 1100
Chris 2 2012/3/1 1200
Joe 1 2012/2/1 1500
Arthur 3 2010/2/1 1200
Joe 1 2010/3/1 900
Arthur 3 2010/3/1 1100
Arthur 3 2010/4/1 1200
Joe 1 2012/4/1 1500
Chris 2 2010/4/1 1800
I've tried using two subqueries, and then comparing them together to find the higher value
SELECT c1.Employee,
c1.TOTAL_SALES
FROM (SELECT Employee,
Sum(sales) AS TOTAL_SALES
FROM EmployeeSales
GROUP BY Employee) c1,
(SELECT Employee,
Sum(sales) AS TOTAL_SALES
FROM EmployeeSales
GROUP BY Employee) c2
WHERE ( c1.TOTAL_SALES > c2.TOTAL_SALES
AND c1.Employee > c2.Employee )
But the resulting query gives me two rows of
Employee TOTAL_SALES
joe 4800
joe 4800
What am I doing wrong?

I would use a CTE.
;With [CTE] as (
Select
[Employee]
,sum([Sales]) as [Total_Sales]
,Row_Number()
Over(order by sum([sales]) Desc) as [RN]
From [EmployeeSales]
Group by [Employee]
)
Select
[Employee]
,[Total_Sales]
From [CTE]
Where [RN] = 1
Example of working code SQL Fiddle:
http://sqlfiddle.com/#!3/bd772/2

To return all employees with the highest total sales, you can use SQL Server's proprietary TOP WITH TIES:
SELECT TOP (1) WITH TIES name, SUM(sales) as total_sales
FROM employees
GROUP BY name
ORDER BY SUM(sales) DESC

SELECT name, SUM(sales) as total_sales
FROM employees
GROUP BY name
ORDER by total_sales DESC
LIMIT 1;
A better solution is to group by an employee id so we are sure they are the same person. Since there can be two Chris's.

I would use a window partition
select * from
(
select
employee
, sum(sales) as sales
, row_number() over
(
order by sum(sales) desc
) as rank
from EmployeeSales
group by employee
) tmp
where tmp.rank = 1
And I agree with what someone said (Shawn) about having an employeeID and group by that for this, rather than the name.
(I removed the partition from the row_number() call as it is not needed for this)

you can use CTE for that
WITH CTE
AS ( select employee , sum(sales) as sales,
ROW_NUMBER() OVER (PARTITION BY employee ORDER BY sum(sales) desc) RN
FROM EmployeeSales)
SELECT employee ,
sales
FROM CTE
WHERE RN =1

Related

Select top 2 sales in each class SQL

I have the table which I want select only top 2 sales in each class, the result is
Sophia A 40
Jennifer A 15
Greg B 50
Jeff B 20
Stella B 20
You could use RANK:
SELECT *
FROM (SELECT *, RANK() OVER(PARTITION BY class ORDER BY sales DESC) AS rnk
FROM tab) sub
WHERE rnk <=2;
window function dense_rank also fulfil expected result condition of sample data
select * from
(select * , dense_rank() over(partition by class order by scores DESC ) as rn
from tablea
) t where rn<=2

Find the 3rd Maximum Salary for each department based on table data

I need to find out the 3rd maximum salary for an employee for each department in a table. if no 3rd maximum salary exists then display 2nd maximum salary. if no 2nd maximum salary exist then find the highest salary. How to achieve this result in sql-server?
The table structure is given below
create table employee1(empid int, empname varchar(10), deptid int, salary money)
insert into employee1
select 1,'a',1, 1000
union
select 1,'b',1, 1200
union
select 1,'c',1, 1500
union
select 1,'c',1, 15700
union
select 1,'d',2, 1000
union
select 1,'e',2, 1200
union
select 1,'g',3, 1500
I have tried the common way of getting the maximum salary for each category using row_number function.
;with cte
as
(
select ROW_NUMBER( ) over( partition by deptid order by salary) as id, * from employee1
)
select * from cte
Select EmpID,empname,deptid,salary
From (
Select *
,RN = Row_Number() over (Partition By deptid Order By Salary)
,Cnt = sum(1) over (Partition By deptid)
From employee1
) A
Where RN = case when Cnt<3 then Cnt else 3 end
Returns
The answer will depend if you want ties and how to handle them. If you want no ties and even if one employee ties with another it becomes the next highest salary then the trick is to use a row_number like the one you are showing only with descending on salary and then use another row_number to reverse it. If you did not want to use row_number a second time you could do it with a few other techniques as well but step 1 is find highest step 2 is to reverse that order
; WITH cteRankSalariesByDepartment AS (
SELECT
*
,RowNum = DENSE_RANK() OVER (PARTITION BY deptid ORDER BY salary DESC)
FROM
employee1
)
, cteReverseRankHighestSalaries AS (
SELECT
*
,RowNum2 = DENSE_RANK() OVER (PARTITION BY deptid ORDER BY RowNum DESC)
FROM
cteRankSalariesByDepartment
WHERE
RowNum <= 3
)
SELECT *
FROM
cteReverseRankHighestSalaries
WHERE
RowNum2 = 1
Per your comment updated to DENSE_RANK() you could simply use it in place of row_number() and you will get your ties.
Just you query needs count and row_number with condition as below:
;with cte
as
(
select ROW_NUMBER( ) over( partition by deptid order by salary desc) as id,
Cnt = count(*) over(partition by deptid), * from employee1
)
select * from cte where ( cnt >= 3 and id = 3 )
or ( cnt < 3 and id = 1 )
you can try a query like below:
select * from
(
select
empid,
empname ,
deptid ,
salary ,
ROW_NUMBER( ) over( partition by deptid order by id desc) as rev_id
from
(
select
ROW_NUMBER( ) over( partition by deptid order by salary) as id,
empid,
empname ,
deptid ,
salary
from employee1
)
t where id<=3
)t where rev_id=1
working demo
You could use UNION
;with cte
as
(
select ROW_NUMBER( ) over( partition by deptid order by salary) as id, * from employee1
)
--get the 3rd highest
select
*
from cte
where id = 3
union
--get the highest / max
select
c.*
from cte c
--this determines the highest which salary for each dept
inner join
(select deptid, max(id) id
from cte
group by deptid) x on x.deptid = c.deptid and x.id = c.id
--this limits it on depts that aren't in the list in the first part of the query
where
c.deptid not in (select deptid from cte where id = 3)
To increase your question I added two employees with the same salary in the third position.
To get this you need the first dense_rank the salary by department. After you need to reverse l the salary rank and get the position 1
try it
DECLARE #employee1 TABLE
(
empid INT,
empname VARCHAR(10),
deptid INT,
salary MONEY
)
INSERT #employee1 Values
(1,'a',1, 1000 )
,(1,'b',1, 1200 )
,(2,'bb',1, 1200 )
,(1,'c',1, 1500 )
,(3,'ccc',1, 1500 )
,(1,'c',1, 15700)
,(1,'d',2, 1000 )
,(1,'e',2, 1200 )
,(1,'g',3, 1500 )
WITH cte_rank
AS (SELECT Dense_rank()
OVER (
partition BY deptid
ORDER BY salary) SalaryRank,
*
FROM #employee1),
cte_final
AS (SELECT Dense_rank()
OVER (
partition BY deptid
ORDER BY salaryrank DESC) SalaryRankReverse,
*
FROM cte_rank
WHERE salaryrank <= 3)
SELECT *
FROM cte_final
WHERE salaryrankreverse = 1
Result
SalaryRankReverse SalaryRank empid empname deptid salary
-------------------- -------------------- ----------- ---------- ----------- ---------------------
1 3 1 c 1 1500.00
1 3 3 ccc 1 1500.00
1 2 1 e 2 1200.00
1 1 1 g 3 1500.00

How to find sum of first three salary where total rows on the table six rows

How to find sum of first three salary where total rows on the table six rows.
id Salary
01 100
02 200
03 300
04 400
05 500
06 600
Try using this.....
SELECT SUM(salary)
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER, salary
FROM tablename) AS foo
WHERE
ROW_NUMBER <= 3
Do you mean this:
SELECT SUM(Salary)
FROM (
SELECT Salary FROM your_table ORDER BY id LIMIT 3
) A
Assuming it to be SQL Server:
SELECT SUM(Salary) As SalaryTotal
(
SELECT TOP 3 * FROM your_table ORDER BY ID
)
If you want SUM of highest 3 salaries then you can ORDER BY Salary:
SELECT SUM(Salary) As SalaryTotal
(
SELECT TOP 3 * FROM your_table ORDER BY salary DESC
)

How to show blank record in sql if duplicate rows exists

My SQL Query Results,
EmployeeID EmployeeName Department
1 John Sales
2 Robert Sales
3 Sudhir Sales
4 Roj Development
Output Should be
EmployeeID EmployeeName Department
1 John Sales
2 Robert
3 Sudhir
4 Roj Development
You can do this:
;WITH CTE
AS
(
SELECT EmployeeID, EmployeeName, Department,
ROW_NUMBER() OVER(PARTITION BY Department ORDER BY(SELECT 1)) rownum
FROM table1
)
SELECT
EmployeeId,
EmployeeName,
CASE rownum
WHEN 1 THEN Department
ELSE ''
END AS Department
FROM CTE
ORDER BY EmployeeID;
SQL Fiddle Demo
Note that: Try not to do these sort of formatting stuff in SQL. SQL is not about formatting.

Is there a way to do something like SQL NOT top statement?

I'm trying to make a SQL statement that gives me the top X records and then all sums all the others. The first part is easy...
select top 3 Department, Sum(sales) as TotalSales
from Sales
group by Department
What would be nice is if I union a second query something like...
select NOT top 3 "Others" as Department, Sum(sales) as TotalSales
from Sales
group by Department
... for a result set that looks like,
Department TotalSales
----------- -----------
Mens Clothes 120.00
Jewelry 113.00
Shoes 98.00
Others 312.00
Is there a way to do an equivalent to a NOT operator on a TOP? (I know I can probably make a temp table of the top X and work with that, but I'd prefer a solution that was just a single sql statement.)
WITH q AS
(
SELECT ROW_NUMBER() OVER (ORDER BY SUM(sales) DESC) rn,
CASE
WHEN ROW_NUMBER() OVER (ORDER BY SUM(sales) DESC) <= 3 THEN
department
ELSE
'Others'
END AS dept,
SUM(sales) AS sales
FROM sales
GROUP BY
department
)
SELECT dept, SUM(sales)
FROM q
GROUP BY
dept
ORDER BY
MAX(rn)
WITH cte
As (SELECT Department,
Sum(sales) as TotalSales
from Sales
group by Department),
cte2
AS (SELECT *,
CASE
WHEN ROW_NUMBER() OVER (ORDER BY TotalSales DESC) <= 3 THEN
ROW_NUMBER() OVER (ORDER BY TotalSales DESC)
ELSE 4
END AS Grp
FROM cte)
SELECT MAX(CASE
WHEN Grp = 4 THEN 'Others'
ELSE Department
END) AS Department,
SUM(TotalSales) AS TotalSales
FROM cte2
GROUP BY Grp
ORDER BY Grp
You can use a union to sum all other departments. A common table expression makes this a little bit more readable:
; with Top3Sales as
(
select top 3 Department
, Sum(sales) as TotalSales
from Sales
group by
Department
order by
Sum(sales) desc
)
select Department
, TotalSales
from Top3Sales
union all
select 'Other'
, SUM(Sales)
from Sales
where Department not in (select Department from Top3Sales)
Example at data.stackexchange.com.
SELECT TOP 3 Department, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY Department
UNION ALL
SELECT 'Others', SUM(s.Sales)
FROM Sales s
WHERE s.Department NOT IN
(SELECT Department
FROM (SELECT TOP 3 Department, SUM(Sales)
FROM Sales
GROUP BY Department) D)