0% found this document useful (0 votes)
21 views4 pages

Sub Queries

This document discusses different types of SQL subqueries including single-row, multiple-row, multiple-column, correlated, and scalar subqueries. It provides examples of how to write queries using each type of subquery and explains how to use the WITH clause to name subqueries.

Uploaded by

Florin Nedelcu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views4 pages

Sub Queries

This document discusses different types of SQL subqueries including single-row, multiple-row, multiple-column, correlated, and scalar subqueries. It provides examples of how to write queries using each type of subquery and explains how to use the WITH clause to name subqueries.

Uploaded by

Florin Nedelcu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 4

SQL statements that accept subqueries include SELECT, INSERT, UPDATE, and DELETE.

Subqueries are not limited to DML—they can also be used in a CREATE TABLE or CREATE
VIEW statement as well.

Types of Subqueries
 Single-row subqueries
 Multiple-row subqueries
 Multiple-column subqueries
 Correlated subqueries (can exist in SELECT, UPDATE, DELETE)
 Scalar subqueries

Single Row Subqueries

01 SELECT EMPLOYEE_ID, LAST_NAME, FIRST_NAME


02 FROM EMPLOYEES
03 WHERE SHIP_ID = (SELECT SHIP_ID
04 FROM EMPLOYEES
05 WHERE LAST_NAME = 'Smith'
06 AND FIRST_NAME = 'Al')
07 AND NOT (LAST_NAME = 'Smith' AND FIRST_NAME = 'Al');

If more than one row is returned, following error is thrown:


Error starting at line 1 in command:
Error report:
SQL Error: ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"

To prevent errors such as above, use where condition on primary key or unique, use aggregated
function without group by or ROWNUM < 2.

Multiple subqueries in one statement


01 SELECT EMPLOYEE_ID, LAST_NAME, FIRST_NAME
02 FROM EMPLOYEES
03 WHERE SHIP_ID = (SELECT SHIP_ID FROM EMPLOYEES
04 WHERE LAST_NAME = 'Smith' AND FIRST_NAME = 'Al')
05 AND NOT (LAST_NAME = 'Smith' AND FIRST_NAME = 'Al')
06 AND SSN = (SELECT SOCIAL_NUMBER FROM EMP_BENEFITS
07 WHERE EMP_BENEFITS_ID = 17);

-datatypes for SSN and SOCIAL_NUMBER should be the same


-comparison conditions- same as for a scalar value

Multiple Row Subqueries

01 SELECT SHIP_ID, LAST_NAME, FIRST_NAME


02 FROM EMPLOYEES
03 WHERE SHIP_ID IN (SELECT SHIP_ID FROM EMPLOYEES WHERE LAST_NAME = 'Smith')
04 ORDER BY SHIP_ID, LAST_NAME;
-comparison conditions- IN, NOT IN, ANY, SOME, ALL
Example: Find all products with a price that’s greater than all of the products in the ‘Luxury’
category:
SELECT * FROM PRODUCTS
WHERE PRICE > ALL (SELECT PRICE FROM PRODUCTS
WHERE CATEGORY = ‘Luxury’);

Write a Multiple-Column Subquery

01 SELECT EMPLOYEE_ID
02 FROM EMPLOYEES
03 WHERE (FIRST_NAME, LAST_NAME) IN
04 (SELECT FIRST_NAME, LAST_NAME
05 FROM CRUISE_CUSTOMERS)
06 AND SHIP_ID = 1;
The datatypes of the columns must match—meaning that the columns on line 3 must match the
datatypes of the columns identified on line 4 or to be comparable datatypes such that automatic
datatype conversion is capable of making them the same datatypes.

Use Scalar Subqueries in SQL

SELECT VENDOR_NAME,
(SELECT TERMS_OF_DISCOUNT FROM INVOICES WHERE INVOICE_ID = 1) AS DISCOUNT
FROM VENDORS
ORDER BY VENDOR_NAME;
Scalar subqueries must always be enclosed in parentheses.
Scalar subquery expressions cannot be used in the following locations:
 In CHECK constraints
 In GROUP BY clauses
 In HAVING clauses
 In a function-based index (which is coming up in Chapter 11)
 As a DEFAULT value for a column
 In the RETURNING clause of any DML statement
 In the WHEN conditions of CASE
 In the START WITH and CONNECT BY clauses
Other than that, they can be used anywhere you would use an expression.

01 INSERT INTO EMPLOYEES


02 ( EMPLOYEE_ID,
03 SHIP_ID)
04 VALUES
05 ( SEQ_EMPLOYEE_ID.NEXTVAL,
06 (SELECT SHIP_ID FROM SHIPS WHERE SHIP_NAME = 'Codd Champion')
07 );

Correlated Subqueries

Correlated subqueries include references to elements of a parent query, and thus, they do not
exist as standalone queries, as do the examples we’ve seen so far.
01 SELECT A.SHIP_CABIN_ID, A.ROOM_STYLE, A.ROOM_NUMBER, A.SQ_FT
02 FROM SHIP_CABINS A
03 WHERE A.SQ_FT > (SELECT AVG(SQ_FT)
04 FROM SHIP_CABINS
05 WHERE ROOM_STYLE = A.ROOM_STYLE)
06 ORDER BY A.ROOM_NUMBER;
Correlated subqueries can exist in SELECT, UPDATE, and DELETE statements. A table alias is
not necessarily required in the subquery if no column name conflict exists. It’s important to note
that correlated subqueries may introduce performance degradation into a query.

UPDATE with a Correlated Subquery

An UPDATE statement can have a correlated subquery:


 In the SET clause
 In the WHERE clause

01 UPDATE INVOICES INV


02 SET TERMS_OF_DISCOUNT = '10 PCT'
03 WHERE TOTAL_PRICE = (SELECT MAX(TOTAL_PRICE)
04 FROM INVOICES
05 WHERE TO_CHAR(INVOICE_DATE, 'RRRR-Q') =
06 TO_CHAR(INV.INVOICE_DATE, 'RRRR-Q'));

01 UPDATE PORTS P
02 SET CAPACITY = (SELECT COUNT(*)
03 FROM SHIPS
04 WHERE HOME_PORT_ID = P.PORT_ID)
05 WHERE EXISTS (SELECT *
06 FROM SHIPS
07 WHERE HOME_PORT_ID = P.PORT_ID);

DELETE with a Correlated Subquery

01 DELETE FROM SHIP_CABINS S1


02 WHERE S1.BALCONY_SQ_FT =
03 (SELECT MIN(BALCONY_SQ_FT)
04 FROM SHIP_CABINS S2
05 WHERE S1.ROOM_TYPE = S2.ROOM_TYPE
06 AND S1.ROOM_STYLE = S2.ROOM_STYLE);

Use the EXISTS and NOT EXISTS Operators

The EXISTS keyword tests for the existence of any rows in a subquery. If no rows are found, the
answer is FALSE. Otherwise, the subquery returns TRUE. NOT EXISTS reverses the results.
01 SELECT PORT_ID, PORT_NAME
02 FROM PORTS P1
03 WHERE EXISTS (SELECT *
04 FROM SHIPS S1
05 WHERE P1.PORT_ID = S1.HOME_PORT_ID);
The entire subquery is executed, even though EXISTS need only know whether or not the
subquery returns any rows—so beware using EXISTS with subqueries that return large numbers
of rows.
It’s worth noting that this sort of query is sometimes referred to as a “semijoin”. A semijoin is a
SELECT statement that uses the EXISTS keyword to compare rows in a table with rows in
another table.

Use the WITH Clause

You can use the keyword WITH to assign a name to a subquery block. Once the name is
assigned, you can reference the name from elsewhere in the query. WITH is considered a clause
of the SELECT statement.
01 WITH
02 PORT_BOOKINGS AS (
03 SELECT P.PORT_ID, P.PORT_NAME, COUNT(S.SHIP_ID) CT
04 FROM PORTS P, SHIPS S
05 WHERE P.PORT_ID = S.HOME_PORT_ID
06 GROUP BY P.PORT_ID, P.PORT_NAME
07 ),
08 DENSEST_PORT AS (
09 SELECT MAX MAX_CT
10 FROM PORT_BOOKINGS
11 )
12 SELECT PORT_NAME
13 FROM PORT_BOOKINGS
14 WHERE CT = (SELECT MAX_CT FROM DENSEST_PORT);

The series of one or more subquery blocks defined before the SELECT statement is referred to as
the subquery factoring clause. WITH can define one subquery factoring clause; it must be
defined before the SELECT statement. Internally, Oracle SQL treats a named query within the
WITH clause as a temporary table or as an inline view. If you use WITH to name a subquery,
that name isn’t recognized within the subquery itself but is recognized in almost every other
location in the overall query.

You might also like