Can anyone please tell me if I am doing this query right? - sql

I have this question in some book I am reading right now..I am a beginner to SQl..learning it..it is not my homework. I am just trying stuff on my own..
Sally wants to query the EMP table and determine how many of the employees live in each of the cities the company has factories in. She writes the following query but it does not work. What is wrong with the way the query is constructed?
SELECT city, COUNT(emp_no) as "Number of Customers"
FROM emp
ORDER BY city
GROUP BY city;
This is what I did by referring to some other query which had count and group By used in it...I think we also need WHERE clause too in this query..how can i do it??
SELECT empid,count(*) “Employee Total”, city
From emp
Group by city;
Please help..thanks :)

The problem with your first query is that order by should come after group by clause,
SELECT city, COUNT(emp_no) as "Number of Customers" FROM emp GROUP BY city Order By city;
The problem with your second query is that you are selecting empid however it's not in Group by list.
Try
SELECT count(*) Employee Total, city From emp Group by city;

Actually the only thing that's wrong with Sally's query is that the ORDER BY clause needs to be at the end:
SELECT city, COUNT(emp_no) as "Number of Customers"
FROM emp
GROUP BY city
ORDER BY city;
Just switching the GROUP BY and ORDER BY around...

SELECT count(*) as "Employee Total", city
From emp
Group by city;
Using the GROUP BY clause on city will group all of the records with the same city together and the aggregate function COUNT(*) will count how many rows are in each city group.
The problem with what you had before was the empid column in the column select. If you are using GROUP BY you can only have aggregate columns and columns in the GROUP BY clause selected. If you were to add empid to the GROUP BY clause the query would have executed but would not have given you the results you were looking for since it would return each empid and a count of 1.

Related

SQL query where Employee works in more than one Department

I have employee table with emp id (emp_id) and department (dep_id) fields. An employee could be working in more than one Department. I want to write a sql query to display unique emp_ids who work in more than one department.
Pl help me to write sql query.
Thx
Answered here: SQL query for finding records where count > 1
You need to use count, group by and having like this.
select emp_id, count(dep_id)
from employee_department
group by emp_id
having count(dep_id)>1
Query
SELECT COUNT(*)
FROM
(
SELECT id_employee, COUNT(*) AS CNT
FROM Department_Employee
GROUP BY id_employee
) AS T
WHERE CNT > 1

SQL - count (*) not working

i want to use a simple count(*) code but there is something wrong.
select fname,lname, dno, count(*) from employee group by dno having count(*);
I am getting the following error:
ERROR at line 4: ORA-00920: invalid relational operator
thank you very much!!
For a group operation to be performed, you need to mention the column names in the group by clause.
So the final query for you would be :
select fname,lname, dno, count(*) from employee group by dno,fname,lname;
Hope this helps. :)
This query has two problems:
1. Invalid use of group by operator
2. Syntax error in having clause.
For step1: Group by clause to be used, make sure you have all columns in group by clause which you are mentioning in select statement.
Biggest demerit of this way is, This grouping makes sub groups and using function like count(*) becomes senseless.
ex- If you have total 10 record of which 2 unique record in "dno" and "lname" is completely unique(which will be obvious practically). Then using group by dno,lname will create total of 10 groups and count(*) will return 1,1,1 value for each one of them. Actual need of group by got lost just to make query run.
So be careful.
For step2 : correct syntax is having count()>1 or count()=2 or anything you want but complete it.
To preserve your logical requirement, you can use analytical function like below:
select e1.fname,e1.lname,e1.dno from
(select fname,lname, dno, count(*) over (partition by dno) as cnt
from employee) e1
where e1.cnt>1;
e.cnt>1 in above query is my assumption. use it as per your need.
No need for "having"
select fname,lname, dno, count(*) from employee group by dno;
You should have an expression for having clause.
Try
select fname,lname, dno, count(*) from employee group by dno having count(*) > 0;
Also I think #Timur is right, there is no need for you to even have the having clause , group by is sufficient
select fname,lname, dno, count(*)
from employee
group by dno,fname,lname;
your have missed few column name in group by , also having should have the relational operator.
please try
select fname,lname, dno, count(1) from employee group by fname,lname,
dno having count(1)>=1;

Select records with maximum value

I have a table that is called: customers.
I'm trying to get the name and the salary of the people who have the maximum salary.
So I have tried this:
SELECT name, salary AS MaxSalary
FROM CUSTOMERS
GROUP BY salary
HAVING salary = max(salary)
Unfortunately, I got this error:
Column 'CUSTOMERS.name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know I should add the name column to the group by clause, but I get all the records of the table.
I know that I can do it by:
SELECT name, salary
FROM CUSTOMERS
WHERE salary = (SELECT MAX(salary) FROM CUSTOMERS)
But I want to achieve it by group by and having clauses.
This requirement isn't really suited for a group by and having solution. The easiest way to do so, assuming you're using a modern-insh version of MS SQL Server, is to use the rank window function:
SELECT name, salary
FROM (SELECT name, salary, RANK() OVER (ORDER BY salary DESC) rk
FROM customers) c
WHERE rk = 1
Mureinik's answer is good with rank, but if you didn't want a windowed function for whatever reason, you can just use a CTE or a subquery.
with mxs as (
select
max(salary) max_salary
from
customers
)
select
name
,salary
from
customers cst
join mxs on mxs.max_salary = cst.salary
There was no need to use group by and having clause there, you know. But if you want to use them then query should be
SELECT name, salary
FROM CUSTOMERS
GROUP BY salary
having salary = (select max(salary) from CUSTOMERS)

How to get all the columns, but have to group by only 2 columns in sql query

I have a table Employees, which has Fields as below:
Employee_name,Employee_id,Employee_status,Employee_loc,last_update_time.
This table does not have any constraint.
I have tried the below query.
select Employee_name, count(1)
from Employees
where Employee_status = 'ACTIVE'
Group by Employee_name,Employee_loc
having count(Employee_name) > 1
order by count(Employee_name) desc
In the select, I need to get Employee_id too.. Can any one help on how to get that?
You can just add Employee_id to the query, and also add it to the group by clause. (Adding it to the grouping won't make any difference in the query results, assuming each employee name each employee id is unique).
If the grouping does make a difference, that implies that some combinations of employee name and location have more than one ID associated with them. Your query would therefore need to decide which ID to return, possibly by using an aggregate function.
SELECT EMPLOYEE_NAME, EMPLOYEE_ID, COUNT(1)
FROM
EMPLOYEES
WHERE
EMPLOYEE_NAME IN
(
SELECT EMPLOYEE_NAME
FROM EMPLOYEES
WHERE Employee_status = 'ACTIVE'
GROUP BY Employee_name,Employee_loc
HAVING COUNT(*) > 1
)
GROUP BY EMPLOYEE_NAME, EMPLOYEE_ID
You can also use partition by clause and select whichever columns you want to see irrespective of the columns you are using for aggregation.
A very short and simple explanation here - Oracle "Partition By" Keyword

How to include column in resultset without including it in group by clause or performing any aggregation on it?

Given a list containing City, EmpName and Salary, sorted by city and EmpName, how to output each EmpName and Salary with the total Salary per City?
Here is what I have got:
select EmpName, sum(Salary) from table group by province;
But it gives me error as I have not included the EmpName in the group by clause and/or am not performing any aggregation on it. How can i achieve the desired results? Any help?
If, what you want, is the sum of the salary in the city for each employee, then you have two options. The first should work in almost any database:
select EmpName, tcity.CitySalary
from t join
(select City, sum(Salary) as CitySalary
from t
group by city
) tcity
on tcity.city = t.city
The second way is to use a window function. Notably, this doesn't work on mysql:
select EmptName, sum(salary) over (partition by city)
from t
SELECT t.City, t.EmpName, t.Salary, x.city_salary
FROM table t,
(SELECT City, SUM(Salary) as city_salary
FROM table
GROUP BY City) x
WHERE x.city = t.city;