How to do sub-query correctly in Oracle?

1

I need to do a sub-query from a table to find all the employees working in the same department that is part of São Paulo, but I'm not getting it. That is, I need to select from the three tables, departments , employees and locations to know where the employees work. And I need to select state_province from table locations while selecting first_name , departments_id and job_id from table employees .

I have the following tables:

Department table

DEPARTMENTS

department_id
department_name
location_id

Local Table

LOCATIONS

location_id
street_address
postal_code
city
state_province
country_id

Employees table

EMPLOYEES

employee_id
first_name
last_name
email
phone_number
hire_date
job_id
department_id

With my current code it does not work, this looks something like this:

SELECT firt_name, department_id, job_id 
FROM locations 
WHERE state_province = (SELECT * 
                        FROM locations 
                        WHERE state_province = 'Sao Paulo');

It starts to give error in the WHERE part since state_province only belongs to the LOCATIONS table and I can not access its attributes. How can I do this sub-query correctly?

I'm new to this select part nested with another select, so excuse me for grotesque errors.

    
asked by anonymous 30.10.2017 / 02:21

1 answer

2

It is always good to think twice before using a subquery to solve a SQL problem, especially if it is something that manipulates large volumes of data or that runs many times because those queries have to be stored in memory for later comparison , worsening application performance.

In the case presented, considering that a EMPLOYEE is related to a DEPARTMENT and this to a LOCATION , you need to express that relationship in your query and I believe you do not need to use subqueries. There are two basic ways to do this with a single query, one defining JOIN clauses and the other using tests in the WHERE clause that cause the creation of an implicit%%.

In both cases all three tables must be involved and the fields must be qualified by the names of the tables to which they belong, to avoid ambiguity. It is possible to set INNER JOIN to the tables, if necessary, to reduce the amount of text in the query, but I will keep the names in full for clarity.

Using the class aliases :

SELECT 
  employees.first_name, 
  employees.department_id, 
  employees.job_id 
FROM 
  employees,
  locations,
  departments
WHERE 
  departments.location_id = locations.location_id and
  employees.department_id = departments.department_id and 
  locations.state_province = 'sao paulo';

This type of query, in my opinion, shows less "verbosity" than using WHERE explicit, making it easier to read. The use of JOIN for this type of purpose is only possible because it is a simple relationship, in which all tables have data to cross, so that the expressed equalities result in an implicit WHERE .

Using INNER JOIN :

As I said above, I prefer using INNER JOIN in these cases because I find it more interesting to put all the rules in one place, but I believe that the "most correct" is to define relationships between tables in WHERE , using clauses FROM . In addition to being the canonical use of SQL, the main advantage is the ability to express more complex relationships.

It follows the same relationship as the previous query, now expressed with two JOIN . I took the liberty of changing the requested fields in INNER JOIN and the filter in SELECT to demonstrate that the columns of all the tables are accessible (note that this is possible in any of the two join methods discussed here). >

SELECT 
  employees.first_name, 
  employees.department_id, 
  employees.job_id ,
  departments.department_name,
  locations.street_address
FROM 
  employees inner join departments on employees.department_id = departments.department_id
            inner join locations on departments.location_id = locations.location_id 
WHERE 
  departments.department_name = 'ti';

The explicit definition of WHERE enables a quicker visual understanding of the relationships established by the query. There are also other types of JOIN that give more control over which of the tables takes precedence in data recovery, something that is not at all possible using JOIN .

Chaining subqueries :

If for some reason it is necessary that the relationship between the tables is not expressed in the WHERE clause nor in the FROM clause as above, it can be reproduced through chained queries (also called "derived queries") in the clause WHERE .

Although we have a "deploying" of the use of SELECT previously shown, this method is somewhat limited in the searchable fields, since only the columns of the "outside" query will be returned:

select * from employees where department_id in (
  select department_id from departments where location_id = (
    select location_id from locations where state_province = 'sao paulo'
  )
);

Note that in order to be able to compare a field with a query in the WHERE clause, this query must also return only one field of the same type. If the subquery returns more than one record and you need to search for all, change the operator from WHERE WHERE to = .

  • SQL Fiddle demonstrating the above queries using some data mounted under the template given in the question: link
  • For more information about using in : link
30.10.2017 / 04:09