Getting total (sum) of employees working under female managers - sqlite - sqlite

I have a coondition where I should show all employees under female managers. So I wrote this query.
select count(E.emp_id) as EmployeeCount, M.name, M.gender
from employee E Join employee M on M.emp_id = E.manager_id
where M.gender ='Female' group by M.name, M.gender
Above query returns
4 Camila Wolstenholme Female
7 Clemmy Lamberts Female
9 Janot Saxon Female
3 Tina Fain Female
But what I want is employees working under each female manager and sum of employees working under all female managers, i.e., 4+7+9+3=23.I want 23 to be shown along with employees working under each female manager. How can I do that

I believe that the following may do what you want :-
SELECT
(SELECT count() FROM employee ee JOIN employee mm ON mm.emp_id = ee.manager_id WHERE m.gender = 'Female' ) AS Total ,
count(E.emp_id) as EmployeeCount, M.name, M.gender,
group_concat(e.name)
FROM employee AS E
JOIN employee M on M.emp_id = E.manager_id
WHERE M.gender ='Female' group by M.name, M.gender
Example/Demo
DROP TABLE IF EXISTS employee;
CREATE TABLE IF NOT EXISTS employee (emp_id INTEGER PRIMARY KEY, name TEXT ,gender TEXT, manager_id INTEGER);
INSERT INTO employee (name,gender,manager_id) VALUES
('Camila Wolstenholme', 'Female',null),
('Clemmy Lamberts','Female',null),
('Janot Saxon','Female',null),
('Tina Fain','Female',null),
('Fred Bloggs','Male',1),
('Anne Smith', 'Female',1),
('Sarah Thompson','Female',1),
('Trudy Mann','Female',1),
('Jane X','Female',2),
('Audrey Wood','Female',2),
('Mary Bartman','Female',2),
('Teresa Owens','Female',2),
('Amanda Jones','Female',2),
('Sophie Alexander','Female',2),
('Andrea Turner','Female',2),
('Jessica Walsh','Female',3),
('Suzy Quertermain','Female',3),
('Alanah Taylor','Female',3),
('Catherine Wilkinson','Female',3),
('Rose Dennis','Female',3),
('Debbie Waterford','Female',3),
('Elaine Bywaters','Female',3),
('Farah Flannagan','Female',3),
('Gina Heartman','Female',3),
('Helen Inglis','Female',4),
('Ingrid Sachs','Female',4),
('Julie Zimmerman','Female',4),
('Frank Smith','Male',null) /* Male Manager */
;
SELECT
(SELECT count() FROM employee ee JOIN employee mm ON mm.emp_id = ee.manager_id WHERE m.gender = 'Female' ) AS Total ,
count(E.emp_id) as EmployeeCount, M.name, M.gender,
group_concat(e.name) AS Manages
FROM employee AS E
JOIN employee M on M.emp_id = E.manager_id
WHERE M.gender ='Female' group by M.name, M.gender
;
DROP TABLE IF EXISTS employee; /* Cleanup Environment */
Result
NULL has been used to indicate a Manager in the absence of an indication of what distinguishes a manager.
Additional
However showing total for each column could be confusing, is it possible to show it as a single row?
The following will show it as a single row with all other values. That is a) the total column is not extracted but instead a row is added via a UNION with the total in the first column and the other columns blanked out.
SELECT
/* (SELECT count() FROM employee ee JOIN employee mm ON mm.emp_id = ee.manager_id WHERE m.gender = 'Female' ) null AS Total ,*/
count(E.emp_id) as EmployeeCount, M.name, M.gender,
group_concat(e.name) AS Manages
FROM employee AS E
JOIN employee M on M.emp_id = E.manager_id
WHERE M.gender ='Female' group by M.name, M.gender
UNION SELECT (SELECT count() FROM employee ee JOIN employee mm ON mm.emp_id = ee.manager_id WHERE mm.gender = 'Female'),'','',''
;
Result

Related

How do I include all max values within a row?

I'm very new to learning SQL, I apologize if my question isn't completely accurate.
The question I'm trying to answer with this query is "What is the most popular music genre in each country?" I've had to use a subquery and it works, but I found that for a few countries in the table, more than one genre has the MAX value. I'm stuck with how to edit my query so that all genres with the max value show in the results. Here is my code, using DB Browser for SQLite:
SELECT BillingCountry AS Country , name AS Genre , MAX(genre_count) AS Purchases
FROM (
SELECT i.BillingCountry, g.name, COUNT(g.genreid) AS genre_count
FROM Invoice i
JOIN InvoiceLine il
ON il.InvoiceId = i.InvoiceId
JOIN TRACK t
ON il.trackid = t.TrackId
JOIN Genre g
ON t.genreid = g.GenreId
GROUP BY 1,2
) sub
GROUP BY 1
Here is an example of the result:
| Country | Genre |Purchase|
|---------|-------|--------|
|Agrentina| Punk | 9 |
|Australia| Rock | 22 |
BUT in running just the subquery to COUNT the purchases, Argentina has two Genres with 9 Purchases (the max number for that country). How do I adjust my query to include both and not just the first one in the row?
You can do it with RANK() window function:
SELECT BillingCountry, name, genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
This will return the ties in separate rows.
If you want 1 row for each country, you could also use GROUP_CONCAT():
SELECT BillingCountry, GROUP_CONCAT(name) AS name, MAX(genre_count) AS genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
GROUP BY BillingCountry

How to assign a 0 for count if the value doesnt exist in the table

I have a table of ratings
|EMPLOYEE|Rating|
1 B
2 B
3 C
4 NULL
5 NULL
6 NULL
and i want to retrieve the count of the grades by each grading like so
Result set
|Rating|Count|
A 0
B 2
C 1
D 0
E 0
I used this query but the grades that isnt in the table will jsut appear as null
select rating,count(rating) from table group by rating
I also used this query which is basically a pivot of the above result set but for some reason it shows 3 rows of repeating data instead of just 1
select (select count(rating) from table where rating = 'E'),(select count(rating) from table where rating = 'D'),(select count(rating) from table where rating = 'C'),(select count(rating) from table where rating = 'B'),(select count(rating) from table where rating = 'A') from table group by rating
If you had a table for the assignable ratings then it would be quite simple (and flexible)
e.g. consider :-
Your existing table.
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (employee TEXT, rating text);
INSERT INTO mytable VALUES (1,'B'),(2,'B'),(3,'C'),(4,null),(5,null),(6,null);
The rating table.
DROP TABLE IF EXISTS rating;
CREATE TABLE IF NOT EXISTS rating (rating);
INSERT INTO rating VALUES('A'),('B'),('C'),('D'),('E');
Then :-
SELECT rating.rating, (SELECT count(*) FROM mytable WHERE rating.rating = mytable.rating) FROM rating;
Results in :-
Flexibility
Add some new ratings e.g. as per :-
INSERT INTO rating VALUES('X'),('Y'),('Z');
And then run:--
SELECT rating.rating, (SELECT count(*) FROM mytable WHERE rating.rating = mytable.rating) FROM rating;
results in :-

Using flat table in MVC

If I have a model that has several tables, and I am joining these tables together into a flat table within my controller class, how do I get the view to be able to access the flat table?
For example, let's say I have three tables in my model (customers, orders, invoices).
Orders are linked to customer by a foreign key (CustomerID), and invoices are linked to orders by a foreign key (OrderID).
In order to see all of this in one flat table (with all customers listed, even if they don't have orders, and all orders listed, even if they don't have invoices), I have the following anonymous type:
var FlatTable = (from a in customers
let CustomerID = a.ID
join b in orders on a.ID equals b.CustomerID into ab
from b in ab.DefaultIfEmpty()
let OrderID = b.ID
join c in invoices on b.ID equals c.InvoiceID into ac
from c in ac.DefaultIfEmpty()
let InvoiceID = c.ID
select new {a.CustomerName, CustomerID, OrderID, b.ProductDescription, InvoiceID, c.InvoiceAmount});
return View(FlatTable.ToList());
Then in my View (which is based on my model), how am I able to access FlatTable.
IList<ViewModel> model = (from a in customers
join b in orders on a.ID equals b.CustomerID into ab
from b in ab.DefaultIfEmpty()
join c in invoices on b.ID equals c.InvoiceID into ac
from c in ac.DefaultIfEmpty()
select new ViewModel() {CustomerName = a.CustomerName, CustomerID = a.ID, OrderID = b.ID, ProductDescription = b.ProductDescription, InvoiceID = c.ID, InvoiceMaount = c.InvoiceAmount}).ToList();

Sql Join between two tables using Entity framework - Trying to bind Gridview data from two tables

I have a gridview and originally I was binding data from one table (Table 1) and it was straightforward
gvUsers.dataSource = class.getUsers()
gvUsers.databind()
Function getUsers () As List (Of Users)
Return (From X in Table1 Select x).ToList()
End Function
However, some of my data are pointing to another table and there is no relationship between tables ( no foreign key)
Table 1
UID Name Age Blood Type Test Type
1 Sam 22 2 3
2 Jane 23 2 4
Table 2
ID Domain Code Description
1 Blood Type A A
2 Blood Type B B
3 Test Type 1 1
4 Test Type 2 2
Currently In the gridView I see Blood Type as values 2 and Test type 3, 4 ( The second table ID) but I should get the Code column values in Table 2.
How can I join those two tables - I know if there is foreign key but the fact a column name is equivelant to row data name makes it hard for me to figure out!
Cheers
Try Code
var result = (from p in Table1.AsEnumerable()
join Blood in Table2.AsEnumerable() on p.BloodType equals Blood .ID
join Test in Table2.AsEnumerable() on p.TestTyoe equals Test .ID
select new With
{
uid = p.UID,
Name = p.name,
Age = p.age,
BloodType = Blood.Code,
TestType = Test .Code
}).ToList();
Sql Query IS :
select UID ,Name,Age,B.Code as BloodType ,T.Code as TestType From Table1
inner join Table2 B on Table1.BloodType = B.ID
inner join Table2 T on Table1.TestType= T.ID
The Used Vb then
Dim result = from p in Table1.AsEnumerable()
join Blood in Table2.AsEnumerable() on p.BloodType equals Blood .ID
join Test in Table2.AsEnumerable() on p.TestTyoe equals Test .ID
select
p.UID,
p.name,
p.age,
Blood.Code,
Test.Code
gvUsers.DataSource = result
Try this one:
select table1.*, table2.* from table1
inner join table2 on table1.Blood Type = table2.id
You can select you desired columns from both tables.

Column Relationships

I realize i'm far off the solution with what i have:
Select FirstName || ' ' || LastName AS Manager From Employee
Where (Select COUNT(ReportsTo) from Employee
group by ReportsTo
order by ReportsTo desc);
ReportsTovalues are the EmployeeID they report to
What i want is to query the name of the employee with the most Employees reporting to them and who they in turn report to without nulls. I'm Not sure how to make the connections between columns values such as ReportsTo to EmployeeID so any explanation would help
For Example the output i would want is two columns say | Fred Jones | Mary Anne| the first being the employee with the most reportsTo with the same value as their EmployeeID and the second being the name of the employee with the same EmployeeID as the first employees ReportTo
Do this step by step:
First step: Count how many employees report to a person.
select reportsto, count(*) from employee group by reportsto;
We can order this result by count(*) and limit it to only get one row, so as to get the person with the most reporters. Only problem is: What to do in case of ties, i.e. two persons have the same highest amount of reporters? SQLite doesn't offer much to help here. We'll have to query twice:
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
);
Next step: Get the name. That means we must access the table again.
select
firstname || ' ' || lastname as manager
from employee
where e1.employeeid in
(
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
)
);
Last step: Get the persons our found managers themselves report to. These can be many, so we group by manager and concatenate all those they report to.
select
e1.firstname || ' ' || e1.lastname as manager,
group_concat(e2.firstname || ' ' || e2.lastname) as reportsto
from employee e1
join employee e2 on e2.employeeid = e1.reportsto
where e1.employeeid in
(
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
)
)
group by e1.firstname || ' ' || e1.lastname;
SELECT e.ReportsTo AS TopManagersEmployeeId, COUNT(e.ReportsTo) AS ReportedBy, m.FirstName + ' ' + m.LastName AS TopManagersName, mm.FirstName + ' ' + mm.LastName AS TheirManagersName FROM Employees e
JOIN Employees m
ON e.ReportsTo = m.EmployeeID
JOIN Employees mm
ON m.ReportsTo = mm.EmployeeID
GROUP BY e.ReportsTo, m.FirstName, m.LastName, mm.FirstName, mm.LastName
Once you have this data, you can do TOP 1 etc. You can also play around with JOIN, and make it INNER JOIN in the second set where Manager's Manager (mm) is being retrieved.

Resources