how to use "not in" operator in oracle cmd? - sql

I am using this code:
create or replace view VIEW_MAXMIN as
select c.country_name,
max(salary) max_salary,
min(salary) min_salary
from employees e,
departments d,
locations l,
countries c
where e.department_id = d.department_id
and d.location_id = l.location_id
and l.country_id = c.country_id = not in(select country_name
from countries
where country_name = 'Mexico');
but always error saying 'SQL command not properly ended'

You can change the joins from legacy Oracle comma joins to ANSI joins and then it looks like you want countries where the name is not Mexico.
Also, if you are aggregating columns and have a column that you are not aggregating then you need to use GROUP BY:
create or replace view VIEW_MAXMIN as
select c.country_name,
max(salary) max_salary,
min(salary) min_salary
from employees e
INNER JOIN departments d
ON (e.department_id = d.department_id)
INNER JOIN locations l
ON (d.location_id = l.location_id)
INNER JOIN countries c
ON (l.country_id = c.country_id)
where c.country_name != 'Mexico'
GROUP BY c.country_name;

Looks like the error you're getting in particular is due to -
l.country_id = c.country_id = not in(select country_name
from countries
where country_name = 'Mexico');
You have 2 equals to condition in one filter statement - like a = b = c
Just - l.country_id = c.country_id would suffice and country_name != 'Mexico' will have to be a separate condition

Related

How can I write this query correctly?

How can I write a query that gives the country name, city, postal code, street address and the number of departments where at least 2 employees work? Below is the query I wrote, but I get "not a GROUP BY expression" error as a result of the query.
SELECT k.COUNTRY_NAME,
l.CITY,
l.POSTAL_CODE,
l.STREET_ADDRESS,
e.DEPARTMENT_ID,
COUNT(EMPLOYEE_ID)
FROM hr.employees e
JOIN hr.departments c
ON (c.DEPARTMENT_ID = e.DEPARTMENT_ID)
JOIN hr.locations l
ON (c.LOCATION_ID = l.LOCATION_ID)
JOIN hr.countries k
ON (k.COUNTRY_ID = l.COUNTRY_ID)
GROUP BY e.DEPARTMENT_ID
HAVING COUNT(EMPLOYEE_ID) > 2;
Because all non-aggregated columns(c.country_name,l.city,l.postal_code,l.street_address,e.department_id) should be listed within the GROUP BY list which is not suitable for your case. Rather use COUNT(.) OVER (..) analytic function with PARTITION BY e.department_id option in order to group by department_id column such as
SELECT DISTINCT *
FROM
(
SELECT c.country_name,
l.city,
l.postal_code,
l.street_address,
e.department_id,
COUNT(e.employee_id) OVER (PARTITION BY e.department_id) AS count
FROM hr.employees e
JOIN hr.departments d
ON d.department_id = e.department_id
JOIN hr.locations l
ON d.location_id = l.location_id
JOIN hr.countries c
ON c.country_id = l.country_id
)
WHERE count >= 2 -- equality is added considering "at least" 2
ORDER BY count
Btw, the parentheses next to the ON clause are redundant
You would first get the set of all departments that have at least 2 employees as follows(atleast_two)
After that you would join the data with the rest of your query and pull the attributes of interest.
with atleast_two
as (select c.DEPARTMENT_ID
,count(employee_id) as cnt_employees
from hr.employees e
join hr.departments c
on (c.DEPARTMENT_ID=e.DEPARTMENT_ID)
group by c.deptid
having count(employee_id)>2
)
select k.COUNTRY_NAME
, l.CITY
, l.POSTAL_CODE
, l.STREET_ADDRESS
, e.DEPARTMENT_ID
, c.cnt_employees
from hr.employees e
join atleast_two c
on (c.DEPARTMENT_ID=e.DEPARTMENT_ID)
join hr.locations l
on (c.LOCATION_ID=l.LOCATION_ID)
join hr.countries k
on (k.COUNTRY_ID=l.COUNTRY_ID);

Left semi Join in Hive for multiple table

How can we use left semi join in multiple tables . For example, in SQL the query to retrieve no. of employees working in US is :
select name,job_id,sal
from emp
where dept_id IN (select dept_id
from dept d
INNER JOIN Location L
on d.location_id = L.location_id
where L.city='US'
)
As IN query is not supported in Hive, how can we write this in Hive.
Seems like a simple inner join
select e.name
,e.job_id
,e.sal
from emp as e
join dept as d
on d.dept_id =
e.dept_id
join location as l
on l.location_id =
d.location_id
where l.city='US'
P.s.
Hive does support IN.
The only issue with your query is that dept_id of emp is not qualified (should be emp.dept_id).
This works:
select name,job_id,sal
from emp
where emp.dept_id IN (select dept_id
from dept d
INNER JOIN Location L
on d.location_id = L.location_id
where L.city='US'
)
Use exists instead:
select e.name, e.job_id, e.sal
from emp e
where exists (select 1
from dept d join
location L
on d.location_id = L.location_id
where l.city = 'US' and d.dept_id = e.dept_id
);
You can refer to the documentation, which covers subqueries in the WHERE clause.
This query appears to be answering the question: What employees work in departments that have a location in the US. You can also do this in the FROM clause with a subquery;
select e.name, e.job_id, e.sal
from emp e join
(select distinct d.dept_id
from dept d join
location L
on d.location_id = L.location_id
where l.city = 'US'
) d
on d.dept_id = e.dept_id;
I should note, though, that "US" is not usually considered a city.
EDIT:
Obviously, if a department can only have one location, then "semi-join" is not necessary. The SELECT DISTINCT can just be SELECT . . . Or, you can use the JOINs as in Dudu's answer. In any case, the EXISTS will work. In many databases it would have good (sometimes the best performance); I'm not sure about the performance implications in Hive.

SQL to join four tables

Display a list of employees names,salaries,and the name of the city in which they work for IT developers who do not earn a comission who work in the operations department in Italy
I did this and it did not work
SELECT e.first_name, e.last_name, e.salary, l.city
FROM employees e
JOIN jobs j
ON (j.job_id = e.job_id)
WHERE
AND e.commission_pct = 0
AND job_title LIKE '%IT Developer%'
JOIN locations l
ON (l.location_id = d.location_id)
AND
(
l.country LIKE '%Italy%'
AND
department_name = 'Operations'
);
http://imgur.com/lex2SyV and this is the link for my logical ERD
SELECT e.first_name,e.last_name,e.salary,l.city
FROM employees e join jobs j
ON(j.job_id = e.job_id)
join departments d ON (d.department_id=e.department_id)
join locations l
ON (l.location_id = d.location_id)
WHERE e.commission_pct = 0 AND
job_title LIKE '%IT Developer%'
AND (l.country LIKE '%Italy%'
AND d.department_name = 'Operations')

How can I resolve an invalid identifier on an Oracle DB query result?

I am new to Oracle DB and I need to list the number of departments per region in the region table.
This is my SQL statement:
SELECT r.region_id, COUNT(d.department_id) "Number of Department"
FROM region r, department d
WHERE r.region_id = d.region_id
GROUP BY r.region_id
I am getting the following error:
"D", "region_id": invalid identifier
How can I correct this?
Edit 1 -
here are the tables from Departments to Regions
Departments Table
Dept_id, Dept_name ,Manager_Id, Location_Id
Locations Table
Location_id, street_add, postal_code, city, state_province, country_id
Countries Table
Country_Id, Country_name, Region_Id
Regions Table
Region_Id, Region_Name
You need to join together all four of your tables, which intuitively makes sense to me from the point of this being an assignment. Something along these lines should work:
SELECT r.region_id, COUNT(d.department_id) "Number of Department"
FROM department d INNER JOIN location l
ON d.location_id = l.location_id
INNER JOIN country c
ON l.country_id = c.country_id
INNER JOIN region r
ON c.region_id = r.region_id
GROUP BY r.region_id

Not a single-group group function Oracle SQL

I have the following table:
I have to find the name and the country of the department with the highest number of employees.
SELECT d.department_name, c.country_name FROM employees e, departments d, locations l, countries c
WHERE d.location_id = l.location_id AND l.country_id = c.country_id
HAVING MAX(e.employee_id) = (SELECT MAX(MAX(employee_id)) FROM employees GROUP BY department_id);
I'm getting a not a single-group group function error. Why is that?
If am not wrong this is what you are looking for
SELECT *
FROM (SELECT d.department_name,
c.country_name
FROM employees e
INNER JOIN departments d
ON e.department_id = d.department_id
INNER JOIN locations l
ON d.location_id = l.location_id
INNER JOIN countries c
ON l.country_id = c.country_id
GROUP BY d.department_name,
c.country_name
ORDER BY Count(1) DESC)
WHERE ROWNUM = 1
is this what you want?
SELECT d.department_name, c.country_name FROM employees e, departments d, locations l, countries c
WHERE d.location_id = l.location_id AND l.country_id = c.country_id
AND ROWNUM = 1
ORDER BY e.employee_id DESC