count() results without using group by - mysql

I am attempting something very similar to last example (Using GROUP BY) on this page:
https://thecodedeveloper.com/mysql-count-function/
Referring to the following table of data:
id name salary department
1 Tom 4000 Technology
2 Sam 6000 Sales
3 Bob 3000 Technology
4 Alan 8000 Technology
5 Jack 12000 Marketing
The following query:
SELECT department, COUNT(*) AS "Number of employees"
FROM employees
GROUP BY department;
Will produce the following output:
department Number of employees
Marketing 1
Sales 1
Technology 3
Except I want to see the number of employees in each department as well as every user in the table.
So I want the output to look like this:
id name salary department employees per department
1 Tom 4000 Technology 3
2 Sam 6000 Sales 1
3 Bob 3000 Technology 3
4 Alan 8000 Technology 3
5 Jack 12000 Marketing 1
I have managed to achieve what I want using a second query to test every result from the first query but it is extremely slow and I am convinced that there is a faster way to do it in a single query.

That's a window count. In MySQL 8.0:
select e.*, count(*) over(partition by d.department) as number_of_employees
from employees e
In earlier versions, an alternative uses a correlated subquery:
select e.*,
(select count(*) from employees e1 where e1.department = e.department) as number_of_employees
from employees e

Related

Query that provides the names of the recruiters that hire more than 3 employees, and the number of employees that were not hired by a recruiter

I'm a bit stuck on this question and was hoping for some help. Here's where I'm at currently.
I have this TEST table of Names. Each Person can either be a recruiter or an employee. The number in Recruited_by is associated with the person_id.
Person_id Name Recruited_by
1 Jean Grayson 1
2 Paul Smith 7
3 John Do Null
4 Alex Lee 7
5 Lisa Kim 7
6 Bob Thompson 3
7 Mike Keen Null
8 Raymond Red 3
9 Alisson Jones 1
10 Kate James 3
Here is the query I have so far which I'm trying to the names of the recruiters that hire more than 3 employees (which will return nothing in this case) and the number of employees that were NOT recruited by anyone (which would be the NULL names).
SELECT T.Name as Employees, COUNT(T1.Name) as Not_hired
FROM Test AS T
WHERE COUNT(T1.Name) IS NULL
LEFT OUTER JOIN Test AS T1
ON T.Recruited_by = T1.Person_id
GROUP BY T.Name
HAVING COUNT(T1.Name) > 3
However this query is returning nothing when I should expect it to return the number of employees who were not hired by a recruiter!
If you want in the results only 1 row with 2 columns then you can do a LEFT join of the table to a query that aggregates to get the ids of the persons that hired more than 3 persons and aggregate again to get the number of persons that were not recruited by anyone:
SELECT GROUP_CONCAT(CASE WHEN t2.Recruited_by IS NOT NULL THEN t1.Name END ORDER BY t1.Name) names,
SUM(t1.Recruited_by IS NULL) total_not_recruited
FROM Test t1
LEFT JOIN (
SELECT Recruited_by
FROM Test
GROUP BY Recruited_by
HAVING COUNT(*) > 3
) t2 ON t2.Recruited_by = t1.Person_id;
You will get the names of the persons that hired more than 3 persons (if they exist) as a comma separated list.
See the demo.

SQL group by function to categorize only the most recent data

So I have this table called title where it stores all of the title held by each employee which will look like this
emp_no
title
start_date
101
Engineer
2019-01-01
101
Senior Engineer
2020-02-01
102
Engineer
2019-01-11
102
Senior Engineer
2020-02-11
103
Engineer
2019-01-21
104
Engineer
2019-01-31
105
Associate
2019-01-01
106
Associate
2019-01-11
106
Manager
2020-02-11
107
Associate
2019-01-21
107
Manager
2020-02-21
108
Associate
2019-01-31
Notice that each employee can have more than 1 title. For example emp 101 title is engineer in 1st January 2019 but got promoted as senior engineer one year later.
Now lets say i want to count how many employees for each position. I have tried using the count function along with group by (to group the number of employee by the title) but the problem is, the SQL query also count the past position of every employee.
To be exact, I only want to include the most recent role that an employee currently has. So in this case, the result I am expecting is
Engineer: 2 employees (because the other 2 has been promotod to senior engineer),
Senior engineer: 2 employees,
Associate: 2 employees (because the other 2 has been promotod to manager),
Manager: 2 employees
Is there some kind of way to achieve that?
NOTE: this table format is from one of the SQL online course that i'm taking so I'm not the one who make the table. and also in the original table in containes tens of thousands of data.
You can use not exists as follows:
select title, count(*) as Count
from your_table t
where not exists
(select 1 from your_table tt
where tt.emp_no = t.emp_no and tt.start_date> t.start_date)
group by title
select title,COUNT(*) numberOfEmp from
(
select distinct emp_no
,(select top 1 title from [dbo].[Tbl_title] a where a.emp_no=m.emp_no
order by [start_date] desc
) title
from [dbo].[Tbl_title] m
) mTable
group by title
I am going to recommend a correlated subquery, but for a very particular reason:
select title, count(*)
from t
where t.start_date = (select max(t2.start_date)
from t t2
where t2.emp_no = t.emp_no
);
The particular reason for suggesting this is that it is easy to modify this for the number of employees "as of" a particular date. For instance, if you want the number of employees as of 2019-01-01, you change the where to:
where t2.emp_no = t.emp_no and t2.start_date <= '2019-01-01'
You can simply filter the data in where condition while counting. Query as follows:
select title, count(distinct emp_no) as Count
from (select emp_np, title, max(start_date) as start_date
from table
group by emp_np, title) subset
group by title

AVG() function is displaying average of all employees instead of average of employees in each town per shop

I want to display the average number of employees in each town. Town can have
This is my data_base:
To clarify it's assumed that employers are part-timers so there may be a situation when they are currently not employed for the sake of exercising OUTER JOIN queries. They can also be assigned to more than 1 shop.
I found the way to do it is to use subquery for AVG function. In a subquery, I will use COUNT to count the number of employees for each town and each shop and the main query will get AVG of those numbers grouping by the town. However while logically I feel the query should be working, it is displaying wrong data. Below is a query that I created.
SELECT s.Town, AVG(a.cnt) AS `Number of employees` FROM
(SELECT COUNT(k.EmpId) AS cnt FROM `Shops and Employees` k
INNER JOIN Shops s ON s.ShopId = k.ShopId
GROUP BY s.Town) AS a, shops s
GROUP BY s.Town
I expected to see something like this:
Town name | AVG of employees per town
-------------------------------------
town1 | 3
town2 | 5
town3 | 1
town4 | 4
Instead I get this:
Town name | AVG of employees per town
-------------------------------------
town1 | 2
town2 | 2
town3 | 2
town4 | 2
Basically what I get is all employes summed divided by the number of towns. I want an average of employees for each town e.g. in town1 I have 2 shops. Shop1 has 2 employees while shop2 has 4 employees. An average for town1 should be 3.
It looks like your problem is that you're not grouping the data by shop in your employee count subquery, so that query is returning the total number of employees per town. Also, you don't need to group by town in that subquery. Without the complete table structure and sample data it's hard to be certain, but I think this is what you really want:
SELECT s.Name as `Town Name`, AVG(se.cnt) AS `AVG employees per shop`
FROM Shops s
JOIN (SELECT ShopId, COUNT(*) AS cnt
FROM `Shops and Employees`
GROUP BY ShopId) se ON se.ShopId = s.ShopId
GROUP BY s.Name

MS Access: Count instances over field based on record-level criteria

I need a query to count the number of orders shipped to each state for each customer. So, let's say John had 5 orders: 2 to Florida, 2 to Alaska, and 1 to Kansas. How do I get those counts for each Customer. I have a query that provides me Customer and Order delivery state, but I cannot figure out how to get the counts. I am looking for something like:
>John FL 2
>John FL 2
>John AK 2
>John KS 1
>John AK 2
>...[Next Customer]...
Thank you.
You need to group it by customer and state and count based on this:
SELECT Customer, State, Count(*) AS Amount
FROM Orders
GROUP BY Customer, State
The resulting calculated field, is named Amount in this example.

Getting table data with total counts

I am having follwoing table
student
sid sname branch semester
1 Vijay CSE 6
2 Ajay MECH 4
3 Riteh CSE 6
4 Nutan CSE 6
5 Riya ETC 4
6 Ritu CSE 6
Here I want to fetch all record and total fetched record count for that i am using following query, but this is not able to fetch all records
select *,count(sid) from students
How can we do this
There are many possible solutions for this,
using subquery
select *,(SELECT COUNT(*) FROM students) totalCOunt from students
using CROSS JOIN
select a.*, b.totalCOunt
from students a, (SELECT COUNT(*) totalCOunt FROM students) b
Try this.
SELECT TotalRecords=Count(*) OVER(), Sname,Branch,Semester
FROM Students