Reason for The multi-part identifier could not be bound - sql

error - The multi-part identifier "Grant.EmpID" could not be bound.
query -
select emp.EmpID,
COUNT(*) as CountRecords,
COUNT(GrantName) AS CountValues
From Employee as emp full join [Grant] as gr
on emp.EmpID = [Grant].EmpID
-- This is the cause for the error ! Change it to gr.EmpID
group by emp.EmpID
Why does this error occur ? Can't I call a person by real name and also by nickname ?

You're aliasing [Grant]. In other words, you're stating that from here on out, [Grant] will be referred to as gr.
Use the ALIAS in the GROUP BY clause, not the tableName.
SELECT emp.EmpID,
COUNT(*) as CountRecords,
COUNT(GrantName) AS CountValues
FROM Employee as emp
FULL JOIN [Grant] as gr
on emp.EmpID = gr.EmpID -- use the alias.
GROUP BY gr.EmpID -- use the alias.
here's the SQL Order of Operation
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause

No you can't because sql server is not a human. imagine we have an Employee table which references itself
select *
from Employee Emp, Employee Mng
where Emp.ManagerID = Mng.EmployeeID
Mng and Emp are two instances of Employee
so if I select
select * from Employee e, Employee
it will return all employee TWO times, because I am telling give me employees once under the name Employee once under the name e (alias)

Related

Is there a way to join two tables and then group by some attribute

Hello I have two tables Emp_774884 and Dept_774884.
Emp_774884 contains
emp_id ename sal deptid
Dept_774884 Contains
deptid dept_name no_of_emp city
I have tried this following query to find the employee with highest salary from every department.
select emp_774884.ename,Max(emp_774884.sal) as salary, dept_774884.DEPT_NAME
from emp_774884 join
dept_774884
on dept_774884.deptid = emp_774884.deptid
group by dept_774884.DEPT_NAME ;
But i am getting the following result
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
I am expecting to get the following columns grouped by their department name
ename salary dept_name
The error seems pretty clear -- you have columns in the select that are unaggregated and not in the group by. Merely adding the columns makes the error go away, but doesn't do what you want.
Oracle has a very nice extension called keep, which does what you want:
select d.DEPT_NAME, max(e.sal) as max_salary,
max(e.ename) keep (dense_rank first order by e.sal desc) as ename_at_max
from emp_774884 e join
dept_774884 d
on d.deptid = e.deptid
group by d.DEPT_NAME ;
Note that this returns only one employee name when there are ties. It is not clear what you want in this case.
Query what you want
select e.ename,d.DEPT_NAME, Max(e.sal) as salary, d.DEPT_NAME
from emp_774884 e join dept_774884 d on ( e.deptid = d.deptid)
join (select dept_774884.DEPT_NAME, Max(emp_774884.sal) as salary, dept_774884.DEPT_NAME
from emp_774884 e1 join
dept_774884 d1
on d1.deptid = e1.deptid
group by dept_774884.deptid) t on (e.deptid = t.deptid)
Now come to the point. Why you are getting
ORA-00979: not a GROUP BY expression 00979. 00000 - "not a GROUP BY expression" *Cause:
*Action:
So this exception come when you use group by exception with some column and at the time of select you use different columns.
In other words
You can only select those columns which you mentioned in group by.
So in your case you use deptid as group by column but you are select other column too.

How do I use a value from the superquery inside a subquery?

I need to create a query that shows the last name of an employee, the employee id, the last name of the manager of that employee and the id of that manager.
The last name, id, and the manager id of that employee is easy to do because it is already in one row, which means that the following is sufficient:
SELECT last_name, employee_id, manager_id FROM employees WHERE manager_id IS NOT NULL;
But to get the last_name of the manager, you have to search the same table by the manager id you got from the employee. The solution I found is:
SELECT last_name,
employee_id,
(SELECT last_name FROM employees WHERE employee_id = manager_id),
manager_id
FROM employees
WHERE manager_id IS NOT NULL;
However, it seems that 'manager_id' doesn't work in the subquery (although I expected that) and the output is NULL (for the manager id, all the other columns do have values).
So my question is, how can I use the manager_id in the subquery?
Side note: The manager_id can be different for each employee, so using a constant value doesn't work.
What you need is a correlated subquery. I strongly, strongly recommend that you use table aliases and qualified column names in all your queries. However, these are particularly important with correlated subqueries.
You should write this query as:
SELECT e.last_name, e.employee_id,
(SELECT m.last_name
FROM employees m
WHERE m.employee_id = e.manager_id
),
e.manager_id
FROM employees e
WHERE e.manager_id IS NOT NULL;
The alias e is an abbreviation for the table reference to employees in the outer query. The alias m is an abbreviation for the table reference in the subquery.
Notice that all column references use the table alias. This makes the query unambiguous, can prevent unexpected errors, and makes the query much easier for you and others to understand.
You could use a self inner join ( a join with the same table)
SELECT
a.last_name
, a.employee_id
, b.last_name
, a.manager_id
FROM employees a
INNER JOIN employees b ON b.employee_id = a.manager_id;
The inner join work only if a.manager_id is not null so you can avoid this where condition
When you want to refer to a table in the outer query, you need to either use the full table name like table.field or, as in your case, if the outer query table is same as the subquery table, you need to assign an alias to the outer query table and use it in the subquery like this:
SELECT
last_name, employee_id,
(SELECT last_name FROM employees WHERE employee_id = emp_outer.manager_id),
manager_id
FROM employees emp_outer
WHERE manager_id IS NOT NULL;

How to alias column in SQL plus

When I write this query in sql plus show me error (ORA-00998: must name this expression with a column alias)
create or replace view vw_salary as select dname ,
(select count(*) from employee where dno=department.dnumber) from department;
Columns in a view need to have a name. So, you need as after the subquery:
create or replace view vw_salary as
select dname,
(select count(*) from employee e where e.dno = d.dnumber
) as NumEmployees
from department d;
I strongly encourage you to use table aliases and qualified column names (that is use the table alias). This is particularly important for correlated subqueries, where it is easy to make a mistake and that is hard to debug.
I also note that the view is called vw_salary, but there is no salary information.
select department.dname, count(employee.dno) as empCount
from department
left join employee
on employee.dno = department.dnumber
group by department.dname
I think this will be more efficient than your current format
It means you need to name the count expression ... try the following, you can change "TheCount" to any name you want to use.
create or replace view vw_salary as select dname ,
(select count(*) AS TheCount from employee where dno=department.dnumber) from department;

How to get result in following scenario

I have table
EMP(id int primary key, name varchar2(15), mgrID int).
Now this table contain all employees(including worker and manager) in company. mgrID column contain id of employee to whom they are reporting.
I want to list the name of worker who is not manager along with their name of manager.
What to do for such query.
I tried nested select query as follows:
select name, (select name from EMP where mgerID is NULL)
as Manager from EMP;
Will this query give proper result?
You could use a self-join:
SELECT e.name AS name, m.name AS manager_name
FROM emp e
JOIN emp m ON e.mgrid = m.id
Your query should fail because you sub-query is uncorrelated and will return multiple results if you have multiple top-level managers.
select name
, (select name from EMP b where b.ID = a.mgerID ) as Manager
from EMP a;
I think the self-join is the more canonical solution, but you should understand the correlated subquery as well as it has many application.

SQL query how to print out manager name?

I need to create a query to display employee name and number along with their super's name and super number. Listing should also include employees who don't have any supervisor.
Select e.ename,e.empno,super.ename,super from emp e;
I don't know how to print out the manager/supervisor name, i just need that.
Join the table to itself using an outer join:
select e.ename, e.empno, super.ename, super.empno
from emp e
left join emp super on super.empno = e.super_empno
The left join will still return rows from emp that do not have a super defined.
EDIT
Due to OP's comment, here's how to do it without a join (using a nasty correlated sub-query):
select
ename,
empno,
(select super.ename from emp where empno = e.super_empno) as super_name,
super_empno
from emp e;