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;
Related
I am trying to find the number of employees in a table that earn exactly the maximum salary of all the employees in the table called tblPerson.
Select Max(x.[No of Employees]) as Number, x.Salary as Salary
from
(
Select Count(Id) as [No of Employees], Salary
from tblPerson
Group by Salary
Having Salary = MAX(Salary)
)x
where x.[No of Employees]=3
Now I know this is a kind of long and complex way of doing it, but I was trying to do it using a derived table. But I am getting the error:
"Column 'x.Salary' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"
My question is, why am I getting this particular error since the main query is a simple Select statement with a where clause. Isn't it??
Mainly, aggregate functions work only with other aggregate functions or grouped by columns.
Why? Because an aggregate function needs to know the set of values to do calculation with.
In you case, the max() will want to use all the data available for the calculation and display a single result (single row) and the other column will want to be displayed row by row. So there's a conflict.
Thank you all. Every answer helped me. However, I think I found a pretty simple way to do it:
Select top 1 Count(Id) as [No of Employees], salary
from tblPerson
Group by Salary
Order by [No of Employees] DESC
select count(*) from tblPerson where salary=(select max(salary) from tblPerson)
You get the error because 'max' is an aggregation, while you have nothing to aggregate the number by.
Select Max(x.[No of Employees]) as Number, x.Salary as Salary
from
(
Select Count(Id) as [No of Employees], Salary
from tblPerson
Group by Salary
Having Salary = MAX(Salary)
)x
---------
Group by Salary -- all other items in your select statement
---------
where x.[No of Employees]=3
however, you can also use a temporary table or variable to find the persons.
To solve this via a variable, you could do the following
declare #maxSalary Decimal
set #maxSalary = (Select max(salary) from tblperson) --insert the max value into a variable
Then either aggregate the persons (or do some other logic):
Select ID from tblperson where salary = #maxSalary
The reason for not using a group by is that using a variable is more efficient, as you search the table instead of aggregating over it.
Create a CTE (RESULT), and using DENSE_RANK function, get the highest salary, together with the EmployeeID's.
The first row of the RESULT table will give the highest salary.
Using the aggregate function COUNT, get the number of Employees with the highest Salary.
with RESULT (EmployeeID, Salary, DenseRank) as
(select EmployeeID, Salary,
DENSE_RANK() over (ORDER BY SALARY DESC) AS DenseRank
from Employee)
select TOP 1 Salary,
(select COUNT(EmployeeID)
from Employee
where Salary = (select TOP 1 Salary)
from RESULT
where DenseRank = 1)
)
from RESULT
where DenseRank = 1;
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)
Given a staff table with the following attributes:
ec,name,code,dob,salary
List the staff members earning more than the average salary.
My solution:
select* from staff where salary > avg(salary);
What is wrong with it?
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
Example using WHERE clause :
select *
from staff
where salary > (select avg(salary) from staff)
Example using HAVING clause :
select deptid,COUNT(*) as TotalCount
from staff
group by deptid
having count(*) > 2
Having clause specifies a search condition for a group or an aggregate. HAVING can be used only with the SELECT statement. HAVING is typically used in a GROUP BY clause. When GROUP BY is not used, HAVING behaves like a WHERE clause.
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
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.