A company wants to know what has happened since the beginning of 1999 on hiring. The human resources manager has asked you to
produce a count of the employees hired since then, broken down by both age and gender simultaneously (i.e. 17 males, 25 females, etc.). Write a query that does that.
This is what I have so far. I couldn't figure out how to merge two columns simultaneously. Any thoughts?
SELECT EmployeeID, COUNT(*) AS "Number of employees"
FROM Employee
WHERE Age and Gender
GROUP BY EmployeeID
HAVING COUNT(*) BEGIN = 1999
I am not pretty much sure about your requirement but the right way to write a query is as following and this may fulfill your requirement with slight changes...
SELECT Gender, COUNT(*) AS "Number of employees", Age
FROM Employee
WHERE year(column_name) >= 1999 --Give a real date column here
GROUP BY Age, Gender
Please provide table structure and complete desired output for the exact answer.
Related
I have an SQL table that I'm trying to write a Query for. The table has four columns, course_id, title, dept_name and credits. Every course is different and has a unique name, but many of the courses share dept_name. Each course has between 1 and 4 credits.
Complete Table
The query I'm trying to write needs to first combine the rows that have the same dept_name, and then only display the resulting departments and credit amounts with a credit sum below 30.
By using the following Query I'm able to return the credit sum grouped by dept_name, but I can't seem to only return the dept_names with a sum of less than 30. Can anyone help me out here? I've tried adding additional WHERE statements, but I just receive errors. Please let me know if this is enough or if more info is needed.
Half-Filtered Table
Use HAVING. For example:
select deptname, sum(credits)
from bk_course
group by dept_name
having sum(credits) < 30
I am working on the northwind database for my sql studies and i`m trying to show How many Employees live in each country and their average age.
This is what i managed to do so far:
select Country,COUNT(EmployeeID) 'AmountOfEmployees',
(select AVG(year (getdate()) - year (birthdate)) from Employees where Employees.Country = 'USA') 'USA_Average_Age',
(select AVG(year (getdate()) - year (birthdate)) from Employees where Employees.Country = 'UK') 'UK_Average_Age'
from Employees
group by Country
and the result is:
I cant seem to manage to get different avgs on the same column for UK and USA. is it even possible?
Hope i was clear with my question.
Would appreciate any help.
Subqueries are not necessary. I may not approve of your calculation for age, but you can use it:
select Country, COUNT(EmployeeID) as NumberOfEmployees,
avg(year(getdate() - year(birthdate)) as average
from Employees
group by Country;
This puts the average on different rows.
Apologies for my simple problem, I am an absolute novice. I have the following code in separate queries
I am attempting to display 3 columns, the average male salary for a set job, average female salary for a set job and the JobID. Separately these queries work however I cannot work out how to combine them.
I have tried multiple solutions from this site for example trying to put multiple select statements inside
and also by using a 'union' solution however cannot get either to work.union This simply compiles them into a single column and sorts via salary not JobID.
SELECT Round(Avg(Salary)) AS AverageMaleSalary, JobID
FROM Employee WHERE Gender = "M"
GROUP BY JobID;
SELECT Round(Avg(Salary)) AS AverageFemaleSalary, JobID
FROM Employee WHERE Gender = "F"
GROUP BY JobID;
You could use conditional aggregation
SELECT JobId,ROUND(AVG(IIF(Gender='F', Salary, NULL))) AS AverageFemaleSalary
,ROUND(AVG(IIF(Gender='M', Salary, NULL))) AS AverageMaleSalary
FROM Employee
GROUP BY JobId;
I have a question about two queries. Will these two queries give the same result? I am trying to find the average salary by department:
Select s1.department, avg(s1.salary)
From
(Select department, salary
From staff
Where salary > 100000) s1
Group by s1.department
vs
select department, avg(salary) as avg_salary
from staff
where salary > 100000
group by department
Yes, it gives the same amounts back.
the bottom query gets data from a sub select which gets its data from the table, whereas the top query gets it straight from the table itself.
There are no additional filters in there. So the result will be the same.
you can test it out however, don't take my word for it.
Considering the following relational schema
customers(id, name, age, address, salary)
I tried a query
SELECT SUM(salary), age FROM customers
GROUP BY age HAVING age > 23 ; ...(1)
I was surprised to see that it worked fine and that I could write a single column condition also in HAVING clause.
Even this is also working
SELECT SUM(salary), age FROM customers
GROUP BY age, salary HAVING age > 23 AND salary >2000; ...(2)
Otherwise, I should have written it like this : (using WHERE clause)
SELECT SUM(salary), age FROM customers
WHERE age > 23 GROUP BY age; ...(3)
And
SELECT SUM(salary), age FROM customers
WHERE age > 23 AND salary >2000 GROUP BY age, salary ; ..(4)
But when I tried with more combinations I found that
that column name must be present in GROUP BY clause also on which condition is applied in HAVING clause.
Am I correct or is it possible to write a single column condition in HAVING clause in any other way also ?
Why is it working because I had earlier studied that we can write only conditions on Aggregate functions in HAVING clause.
You're generally correct. Important thing is to understand grouping at all.
When using GROUP BY, server scans 'rows' and buckets them into some 'groups'. Then every 'group' works as a single new row. When operating these 'new lines' - in SELECT, HAVING or ORDER clauses - server needs to know 'attribute values' of them. These attribute values are aggregations of rows' attribute values or expressions with these aggregations.
When some attribute or expression used in the GROUP BY clause, it's aggregation values are quite deterministic, so server give us ability to simplify process. We can write something like
SELECT object_type, count(*)
FROM user_objects
GROUP BY object_type
HAVING MAX(object_type) like '%O%'
ORDER BY MIN(object_type)
It would work fine if we do this. But we can write simply
SELECT object_type, count(*)
FROM user_objects
GROUP BY object_type
HAVING object_type like '%O%'
ORDER BY object_type
which means exact the same. If column does not mentioned into the GROUP BY values - rule above became not true, so we cannot use it directly, without aggregation.
SELECT SUM(salary), age
FROM customers
GROUP BY age, salary
HAVING age > 23 AND salary >2000;
This gives you one record per age and salary, as you group by these. Later you remove some of the result lines. The sum of the salary is of course the salary itself.
If these are your records for instance:
salary age something
1000 30 100
1000 30 200
2000 30 300
2000 40 400
then you group like this:
salary age something
1000 30 100
200
2000 30 300
2000 40 400
For the group 1000/30 the sum(something) is 300 and avg(something) is 150. But the sum(salary) is 1000 and avg(salary) is 1000 and min(salary) is 1000, and so on, because it is just one salary value you are talking about.
The HAVING clause then removes lines from the result where age is over 23 and salary over 2000. You could have removed these records from evaluation by using a WHERE clause instead, thus saving the dbms some work. But you made the dbms collect all age and salary groups first, only to say which ones you dismiss afterwards.
I agree though that it would be better the DBMS raised an error telling you that sum(salary) makes no sense as it is just the one salary of the group.