By Sanjay Mishra, Alan Beaulieu
Book Price: $39.95 USD
£28.50 GBP
PDF Price: $31.99
Cover | Table of Contents | Colophon
cust_order table holds a foreign key to the
employee table, which
signifies the salesperson responsible for
a particular order. Physically, this means that the
cust_order table contains a column holding
employee ID numbers, and that, for any given order, the employee ID
number indicates the employee who sold that order. If you find this
confusing, simply use the diagram as an illustration of the tables
and columns found within our database. As you work your way through
the SQL examples in this book, return occasionally to the diagram,
and you should find that the relationships start making sense.SELECT <one or more things> FROM <one or more places> WHERE <zero, one, or more conditions apply>
customer table:
SELECT cust_nbr, name, region_id
FROM customer;
CUST_NBR NAME REGION_ID
---------- ------------------------------ ----------
1 Cooper Industries 5
2 Emblazon Corp. 5
3 Ditech Corp. 5
4 Flowtech Inc. 5
5 Gentech Industries 5
6 Spartan Industries 6
7 Wallace Labs 6
8 Zantech Inc. 6
9 Cardinal Technologies 6
10 Flowrite Corp. 6
11 Glaven Technologies 7
12 Johnson Labs 7
13 Kimball Corp. 7
14 Madden Industries 7
15 Turntech Inc. 7
16 Paulson Labs 8
17 Evans Supply Corp. 8
18 Spalding Medical Inc. 8
19 Kendall-Taylor Corp. 8
20 Malden Labs 8
21 Crimson Medical Inc. 9
22 Nichols Industries 9
23 Owens-Baxter Corp. 9
24 Jackson Medical Inc. 9
25 Worcester Technologies 9
26 Alpha Technologies 10
27 Phillips Labs 10
28 Jaztech Corp. 10
29 Madden-Taylor Inc. 10
30 Wallace Industries 10part table. To inspect the data in the table, you
issue the following query:SELECT part_nbr, name, supplier_id, status, inventory_qty FROM part;
part table contains 10,000 items, the
result set returned by the query would consist of 10,000 rows, each
with 5 columns. You would then load the 10,000 rows into memory and make
your modifications.part table.
Without the ability to specify the rows to modify, you have no choice
but to delete all rows in the table and re-insert all 10,000 rows:DELETE FROM part;
INSERT INTO part (part_nbr, name, supplier_id, status, inventory_qty)
VALUES ('XY5-1002', 'Wonder Widget', 1, 'IN-STOCK', 1);
/* 9,999 more INSERTs on the wall, 9,999 more INSERTS . . . */
part table only for those parts supplied by Acme
Industries. Since the supplier's name is stored in
the supplier table, you must include both the
part and supplier tables in the
FROM clause:SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty, s.supplier_id, s.name FROM part p, supplier s;
part table. To inspect the data in the table, you
issue the following query:SELECT part_nbr, name, supplier_id, status, inventory_qty FROM part;
part table contains 10,000 items, the
result set returned by the query would consist of 10,000 rows, each
with 5 columns. You would then load the 10,000 rows into memory and make
your modifications.part table.
Without the ability to specify the rows to modify, you have no choice
but to delete all rows in the table and re-insert all 10,000 rows:DELETE FROM part;
INSERT INTO part (part_nbr, name, supplier_id, status, inventory_qty)
VALUES ('XY5-1002', 'Wonder Widget', 1, 'IN-STOCK', 1);
/* 9,999 more INSERTs on the wall, 9,999 more INSERTS . . . */
part table only for those parts supplied by Acme
Industries. Since the supplier's name is stored in
the supplier table, you must include both the
part and supplier tables in the
FROM clause:SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty, s.supplier_id, s.name FROM part p, supplier s;
p.supplier_id and s.supplier_id
are identical and where the s.name column matches
'Acme Industries'. If Acme Industries supplies
only 50 of the 10,000 parts in your database, you will end up
discarding 999,950 of the 1,000,000 rows returned by your query.SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty, s.supplier_id, s.name FROM part p, supplier s WHERE s.supplier_id = p.supplier_id AND s.name = 'Acme Industries';
part and supplier tables will
only be included in the final result set if both tables share a
common value for the supplier_id column, and if
the value of the name column in the supplier table
matches 'Acme Industries'. Any other permutation
of data from the two tables would evaluate to FALSE and be discarded.SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty, s.supplier_id, s.name FROM part p, supplier s WHERE s.supplier_id = p.supplier_id AND s.name = 'Acme Industries';
|
Intermediate result
|
Final result
|
|---|---|
|
WHERE TRUE AND TRUE
|
TRUE
|
|
WHERE FALSE AND FALSE
|
FALSE
|
|
WHERE FALSE AND TRUE
|
FALSE
|
|
WHERE TRUE AND FALSE
|
FALSE
|
s.supplier_id = p.supplier_id s.name = 'Acme Industries' supplier_id = (SELECT supplier_id FROM supplier WHERE name = 'Acme Industries')
SELECT department.location_id, department.name, location.regional_group
FROM department JOIN location
ON department.location_id = location.location_id;
LOCATION_ID NAME REGIONAL_GROUP
----------- -------------------- ---------------
122 ACCOUNTING NEW YORK
124 RESEARCH DALLAS
167 OPERATIONS BOSTON
department table, whereas each
department's region is stored in the
location table. Notice the JOIN keyword between
the two tables names in the FROM clause. The SELECT list may include
columns from any of the tables specified in the FROM clause. The
clause starting with the keyword ON specifies the join condition.
SELECT department.location_id, department.name, location.regional_group
FROM department JOIN location
ON department.location_id = location.location_id;
LOCATION_ID NAME REGIONAL_GROUP
----------- -------------------- ---------------
122 ACCOUNTING NEW YORK
124 RESEARCH DALLAS
167 OPERATIONS BOSTON
department table, whereas each
department's region is stored in the
location table. Notice the JOIN keyword between
the two tables names in the FROM clause. The SELECT list may include
columns from any of the tables specified in the FROM clause. The
clause starting with the keyword ON specifies the join condition.location_id column of the
department table is equated with the
location_id column of the
location table:
ON department.location_id = location.location_id;
location_id column from the
department and location tables;
however, the location_id column is not selected:SELECT d.dept_id, d.name, l.regional_group FROM department d JOIN location l ON d.location_id = l.location_id;
SELECT supplier_id, name
FROM supplier s
WHERE EXISTS (SELECT *
FROM part p
WHERE p.inventory_qty < 10
AND p.supplier_id = s.supplier_id);
inventory_qty and supplier_id
columns of the part table, this query could result
in multiple, full-table scans of the part table.
It's possible to restate the query using a join. For
example:SELECT s.supplier_id, s.name FROM supplier s JOIN part p ON p.supplier_id = s.supplier_id WHERE p.inventory_qty < 10;
DESC employee
aggregate_function([DISTINCT | ALL] expression)
aggregate_function([DISTINCT | ALL] expression)
SELECT MAX(salary) FROM employee;
MAX(SALARY)
-----------
5000
cust_order table:
DESC cust_order
Name Null? Type
-------------------------------- -------- --------------
ORDER_NBR NOT NULL NUMBER(7)
CUST_NBR NOT NULL NUMBER(5)
SALES_EMP_ID NOT NULL NUMBER(5)
SALE_PRICE NUMBER(9,2)
ORDER_DT NOT NULL DATE
EXPECTED_SHIP_DT NOT NULL DATE
CANCELLED_DT DATE
SHIP_DT DATE
STATUS VARCHAR2(20)
SELECT cust_nbr, COUNT(order_nbr)
FROM cust_order
GROUP BY cust_nbr;
CUST_NBR COUNT(ORDER_NBR)
---------- ----------------
1 8
4 4
5 6
8 2
cust_nbr; therefore, it produced
one output row for each distinct value of
cust_nbr. Each data value for a given customer
represents a summary based on all rows for that customer.cust_nbr in the SELECT list of the query in our
most recent example also appears in the GROUP BY clause. If you have
a mix of aggregate and nonaggregate expressions in the SELECT list,
SQL expects that you are trying to perform a GROUP BY operation, and
you must also include a GROUP BY clause in your query. Oracle returns
an error if you fail to do so. For example, if you omit the GROUP BY
clause, the following error is returned:
SELECT cust_nbr, sales_emp_id, COUNT(order_nbr)
FROM cust_order;
SELECT cust_nbr, sales_emp_id, COUNT(order_nbr)
*
ERROR at line 1:
ORA-00937: not a single-group group function
SELECT cust_nbr, COUNT(order_nbr)
FROM cust_order
GROUP BY cust_nbr
HAVING cust_nbr < 6;
CUST_NBR COUNT(ORDER_NBR)
---------- ----------------
1 8
4 4
5 6
cust_nbr < 6 as a condition. Orders for all
customers were counted, but only those groups that matched the
specified HAVING condition were returned as the result.WHERE cust_nbr < 6 instead of
HAVING cust_nbr < 6, because the WHERE clause
eliminates rows prior to summarization, whereas HAVING eliminates
groups post-summarization. A better version of the previous query
would be:SELECT cust_nbr, COUNT(order_nbr) FROM cust_order WHERE cust_nbr < 6 GROUP BY cust_nbr;
SELECT cust_nbr, COUNT(order_nbr)
FROM cust_order
GROUP BY cust_nbr
HAVING COUNT(order_nbr) > 2;
CUST_NBR COUNT(ORDER_NBR)
---------- ----------------
1 8
4 4
5 6
An economic slowdown has resulted in budget constraints for many employers, especially in the IT industry. Budget constraints have forced companies to take a second look at the money spent on employee compensation. Some companies have had to downsize their workforce, others have had to cut down employee bonuses, while still others have cut the employee base salaries. Your company is no exception, and is also under financial pressure. Your CEO must take a serious look at the compensation structure of the employees at various levels in various departments in the company.Your CEO calls on you to query the Human Resources database and help him collect data. By this time, you've already heard the rumors of upcoming "reductions in force" (RIFs) and compensation cuts. This is your golden opportunity to impress your CEO with your skills, to make sure you are not affected by the RIFs. Mess up now, and you can be pretty sure that you have to start looking for another job in this increasingly competitive job market.
SELECT dept_id, SUM(salary)
FROM employee
GROUP BY dept_id;
DEPT_ID SUM(SALARY)
---------- -----------
10 8750
20 9900
30 9400