How use GROUP BY and MAX on Strings? [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 29 days ago.
Improve this question
I would like to group the following table.
I want to group the table with Department_ID and Employee_ID, and display the team that occurs the most. The goal table should look like this:
SELECT [Department_ID]
,[Employee_ID]
, max(team_id)
FROM [AdventureWorksLT2019].[dbo].[table]
GROUP BY
[Department_ID]
,[Employee_ID]
But i do not get the expected results.
Try it out: https://dbfiddle.uk/2HHLZQe-

A few ways you could do this, the de-facto solution is to use a row_number window:
with c as (
select Department_ID, Employee_ID, Team_ID, Count(Team_ID) q
from t
group by Department_ID, Employee_ID, Team_ID
), rn as (
select Department_ID, Employee_ID, Team_ID,
Row_Number() over(partition by Department_ID, Employee_ID order by q desc) rn
from c
)
select Department_ID, Employee_ID, Team_ID as most_occured_values
from rn
where rn = 1;
Pointed out by #Charlieface this can be more compactly expressed as follows - I'll leave the above as it helps illustrate the process
with c as (
select
Department_ID,
Employee_ID,
Team_ID,
Count(*) q,
Row_Number() over(partition by Department_ID, Employee_ID order by count(*) desc) rn
from t
group by Department_ID, Employee_ID, Team_ID
)
select Department_ID, Employee_ID, Team_ID as most_occured_values
from c
where rn = 1;
Modified Fiddle

I just added a MIN function it isn't the best solution but works.
SELECT*
FROM [dbo].[table]
SELECT [Department_ID]
,[Employee_ID]
, MIN(team_id) as most_occured_values
FROM [dbo].[table]
GROUP BY
[Department_ID]
,[Employee_ID]

--Check this
Select [Department_ID],[Employee_ID],[Team_ID] ,counts
from (Select [Department_ID],[Employee_ID],[Team_ID],Count(*) counts,Row_number () over (Partition by [Department_ID],[Employee_ID] Order by Count(*) desc) TeamIDCount
From #temp
Group by [Department_ID],[Employee_ID],[Team_ID])T
Where TeamIDCount=1

SELECT TOP 1 department_id ,employee_id ,team_id
FROM
(
SELECT Department_ID,Employee_ID, count(team_id) as COUNT,team_id
FROM TABLE_NAME
GROUP BY Department_ID,Employee_ID,team_id ) t
ORDER BY COUNT desc

Related

rowcount query in Oracle 8i

I have a table Department_history and here is the count of records for each department.
select department_name, Id, count(1) total_rows_COUNT from Department_history
where
group by Department_history,id
order by 2 desc
result:
department_name ID total_rows_COUNT
Accounting 4564 556
Finance 3434 671
Marketing 4353 234
IT 1233 454
I want to keep only the 10 records for each department in the table.
if run this below query for each department like this, it works.
delete from Department_history a1
where
and a1.report_runtime NOT IN
(
select report_runtime
from (
select a.*, rank() over ( partition by department_name, id order by report_runtime desc) r
from Department_history a
) rs
where r <= 10 and department_name = 'Accounting'
)
and department_name = 'Accounting'
But I don't want to individually run this deletion for each department.
how can I run one query that deletes the data for each department_name (if it is >10 records). I tries this. but it doesn't work.
delete from Department_history a1
where
and a1.report_runtime NOT IN
(
select report_runtime
from (
select a.*, rank() over ( partition by department_name, id order by report_runtime desc) r
from Department_history a
) rs
where r <= 10
)
Can someone please advise?
test sample:
create table tst as select owner, view_name from all_views;
delete from tst
where owner||'::'||view_name in
(
select owner||'::'||view_name from (
select owner, view_name, rank() over (partition by owner order by view_name) r from tst
) where r > 10
)
your updated sql:
delete from Department_history
where id NOT IN
(
select id
from (
select id, rank() over ( partition by department_name
order by report_runtime desc) rnk
from Department_history
) s
where s.rnk <= 10
)
Try this. It's similar to what you already tried, but the not in clause should be checking against all 3 identifying columns, department_name, id, report_runtime, not just report_runtime. Otherwise, you might accidentally delete the wrong rows.
I also used row_number instead of rank. I think it's the better choice for your requirement. Though based on your description of the data, I don't think it actually makes a difference in this case.
delete from department_history
where (department_name, id, report_runtime)
not in (select department_name, id, report_runtime
from (select department_name, id, report_runtime,
row_number() over (partition by department_name, id order by report_runtime desc) as rn
from department_history)
where rn <= 10)

Query to get the "MAX COUNT"

Guys I have the following query:
select count(*) AS num_items
from desc_look
group by dept
This query returns the number of items in each department. However I can't get ONLY the department with the higher number of items.
I've been trying to use this to retrieve the name and id of the department with most items
select dept, desc_up
from desc_look
where (select count(*) AS num_items
from desc_look
group by dept)
However I keep getting an error ORA-00936 and I don't know why.
I know I can't user MAX(COUNT(*)) but is there a way to workaround this?
select * from
(
select count(*) AS num_items
from desc_look
group by dept
order by count(*) desc
) tmp
WHERE ROWNUM = 1;
Also have a look on howto limit the records in Oracle.
This version is basically the same as juergen's, but using an analytic function instead of an aggregate (GROUP BY) for counting:
SELECT t.dept, t.desc_up FROM
(SELECT dept, desc_up,
COUNT(*) over (partition BY dept) dept_count
FROM desc_look
ORDER BY dept_count DESC
) t
WHERE rownum = 1
If you're on Oracle 12, the inline view is not needed because you can use the row-limiting clause (FETCH FIRST ...):
SELECT dept, desc_up,
COUNT(*) over (partition BY dept) dept_count
FROM desc_look
ORDER BY dept_count DESC
FETCH FIRST 1 ROW ONLY
You might try something like this:
SELECT dept, num_items FROM (
SELECT dept, COUNT(*) AS num_items
, ROW_NUMBER() OVER ( ORDER BY COUNT(*) DESC ) AS rn
FROM desc_look
GROUP BY dept
) WHERE rn = 1;
i think this may help you
select count(*) AS num_items
from desc_look
group by dept
order by count(*) desc
limit 1

Finding department having maximum number of employee

I have a table employee
id name dept
1 bucky shp
2 name shp
3 other mrk
How can i get the name of the department(s) having maximum number of employees ? ..
I need result
dept
--------
shp
SELECT cnt,deptno FROM (
SELECT rank() OVER (ORDER BY cnt desc) AS rnk,cnt,deptno from
(SELECT COUNT(*) cnt, DEPTNO FROM EMP
GROUP BY deptno))
WHERE rnk = 1;
Assuming you are using SQL Server and each record representing an employee. So you can use window function to get the result
WITH C AS (
SELECT RANK() OVER (ORDER BY dept) Rnk
,name
,dept
FROM table
)
SELECT TOP 1 dept FROM
(SELECT COUNT(Rnk) cnt, dept FROM C GROUP BY dept) t
ORDER BY cnt DESC
With common table expressions, count the number of rows per department, then find the biggest count, then use that to select the biggest department.
WITH depts(dept, size) AS (
SELECT dept, COUNT(*) FROM employee GROUP BY dept
), biggest(size) AS (
SELECT MAX(size) FROM depts
)
SELECT dept FROM depts, biggest WHERE depts.size = biggest.size
Based on one of the answer, Let me try to explain step by step
First of all we need to get the employee count department wise. So the firstly innermost query will run
select count(*) cnt, deptno from scott.emp group by deptno
This will give result as
Now out of this we have to get the one which is having max. employee i.e. department 30.
Also please note there are chances that 2 departments have same number of employees
The second level of query is
select rank() over (order by cnt desc) as rnk,cnt,deptno from
(
select count(*) cnt, deptno from scott.emp group by deptno
)
Now we have assigned ranking to each department
Now to select rank 1 out of it. we have a simplest outer query
select * from
(
select rank() over (order by cnt desc) as rnk,cnt,deptno from
(
select count(*) cnt, deptno from scott.emp group by deptno
)
)
where rnk=1
So we have the final result where we got the department which has the maximum employees. If we want the minimum one we have to include the department table as there are chances there is a department which has no employees which will not get listed in this table
You can ignore the scott in scott.emp as that is the table owner.
The above SQL can be practised at Practise SQL online

Top 2 Salary Grouped By Department

Below is the table I am referring to.
I want to find ou the 2 Employees in each department with highest salary.
Further to the above answer, if there are ties (multiple employees sharing the same salary), you can use the following to bring them all through instead of just picking two at random (which is what the ROW_NUMBER clause will do)
SELECT *
FROM (
SELECT *, DENSE_RANK() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2
Use ROW_NUMBER() to get the top salaries per Department, then select the first two records from each departmental partiton:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2

Running Order by on column alias

I am trying to run following SQL query on northwind database :
SELECT * FROM (
SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY Joinning DESC) rownum,
LastName, Country, HireDate AS Joinning
FROM Employees
WHERE Region IS NOT NULL
) r
It's giving me the error :
Invalid column name 'Joinning'.
The 'rownumber' is required for pagination.
Can anybody please suggest how I can sort on the Joining alias with the rownumber generated ?
--A possible work around
Just figured out a work around; please suggest if anything is wrong or need changes :
SELECT ROW_NUMBER() OVER (ORDER BY Joinning DESC) rownum,* FROM (
SELECT
LastName, Country, HireDate AS Joinning
FROM Employees
WHERE Region IS NOT NULL
) r
--To put further where clause on row number(what I wanted to do for pagination):
With myres as(
SELECT ROW_NUMBER() OVER (ORDER BY Joinning DESC) rownum,* FROM (
SELECT
LastName, Country, HireDate AS Joinning
FROM Employees
WHERE Region IS NOT NULL
) a
) Select * from myres where myres.rownum > 0 and myres.rownum < = 0+20
Try
SELECT * FROM (
SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY HireDate DESC) rownum,
LastName, Country, HireDate AS Joinning
FROM Employees
WHERE Region IS NOT NULL
) r
Hope you ahve joinning in your table.
The order by clause is usually given at the last of the query like this :
SELECT * FROM (
SELECT DISTINCT ROW_NUMBER() rownum,
LastName, Country, HireDate AS Joinning)
FROM Employees
WHERE Region IS NOT NULL ORDER BY Joinning DESC)
Hope this helps you!
Use Original Name of the field, That will work just fine HireDate
SELECT * FROM (
SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY HireDate DESC) rownum,
LastName, Country, HireDate AS Joinning
FROM Employees
WHERE Region IS NOT NULL
) r