Lab #12: Oracle
You begin four steps after running the create_oracle_store.sql
, the seed_oracle_store.sql
, apply_lab5_oracle.sql
, apply_oracle_lab6.sql
, apply_oracle_lab7.sql
, apply_oracle_lab8.sql
, apply_oracle_lab9.sql
, apply_oracle_lab10.sql
, and apply_oracle_lab11.sql
scripts. You should create the apply_oracle_lab12.sql
script as follows:
-- This calls Lab #11, Lab #11 calls Lab #10, Lab #10 calls Lab #9, Lab #9 calls Lab #8, Lab #8 calls Lab #7, Lab #7 calls Lab #6, Lab #6 calls Lab #5, and Lab #5 calls both the Creation and Seed script files. @../lab11/apply_oracle_lab11.sql SPOOL apply_oracle_lab12.txt ... insert code here ... SPOOL OFF |
- [3 points] Create the following
CALENDAR
table as per the specification.
Implementation Note: The CALENDAR
table has a range relationship to the TRANSACTION
table created in the prior lab.
Business Rule: The CALENDAR
table provides end points to bracket transaction dates into calendar months.
System Logic: In future refinement this table may become multilingual and support regional languages based on HTML request header information.
Table Name: CALENDAR | |||||
---|---|---|---|---|---|
Column Name | Constraint | Data Type |
Physical Size |
||
Type | Reference Table | Reference Column | |||
CALENDAR_ID | PRIMARY KEY | Integer | Maximum | ||
CALENDAR_NAME | NOT NULL | String | 10 | ||
CALENDAR_SHORT_NAME | NOT NULL | String | 3 | ||
START_DATE | NOT NULL | Date | Date | ||
END_DATE | NOT NULL | Date | Date | ||
CREATED_BY | FOREIGN KEY | SYSTEM_USER | SYSTEM_USER_ID | Integer | Maximum |
CREATION_DATE | NOT NULL | DATE | Date | ||
LAST_UPDATED_BY | FOREIGN KEY | SYSTEM_USER | SYSTEM_USER_ID | Integer | Maximum |
LAST_UPDATE_DATE | NOT NULL | DATE | Date |
- [3 points] Seed the
CALENDAR
table with the following data.
Data Entry to Table: CALENDAR | |||
---|---|---|---|
Calendar Month Name |
Calendar Short Month Name |
Start Date |
End Date |
January | JAN | 01-JAN-2009 | 31-JAN-2009 |
February | FEB | 01-FEB-2009 | 28-FEB-2009 |
March | MAR | 01-MAR-2009 | 31-MAR-2009 |
April | APR | 01-APR-2009 | 30-APR-2009 |
May | MAY | 01-MAY-2009 | 31-MAY-2009 |
June | JUN | 01-JUN-2009 | 30-JUN-2009 |
July | JUL | 01-JUL-2009 | 31-JUL-2009 |
August | AUG | 01-AUG-2009 | 31-AUG-2009 |
September | SEP | 01-SEP-2009 | 30-SEP-2009 |
October | OCT | 01-OCT-2009 | 31-OCT-2009 |
November | NOV | 01-NOV-2009 | 30-NOV-2009 |
December | DEC | 01-DEC-2009 | 31-DEC-2009 |
- [4 points] Import and merge the new
*.csv
files.
Implementation Note: The first *.csv
file contained incorrect values. This one reverses a number of rentals and adds new ones. Download this zip file. A merge is not necessary. You may accomplish the addition by using an INSERT
statement. You need to ignore the TRANSACTION_ID
value and use a transaction_reversal_s1.nextval
value.
System Logic: Create the TRANSACTION_REVERSAL
table as qualified below by leveraging the existing structure of the TRANSACTION
table. Oracle provides the DBMS_METADATA.GET_DDL
to create a starting point for an external table definition, and you can simply select the structure in MySQL (see the hint).
Table Name: TRANSACTION_REVERSAL | |||||
---|---|---|---|---|---|
Column Name | Constraint | Data Type |
Physical Size |
||
Type | Reference Table | Reference Column | |||
TRANSACTION_ID | PRIMARY KEY | Integer | Maximum | ||
TRANSACTION_ACCOUNT | String | 15 | |||
TRANSACTION_TYPE | Integer | Maximum | |||
TRANSACTION_DATE | Date | Date | |||
TRANSACTION_AMOUNT | Float | Maximum | |||
RENTAL_ID | Integer | Maximum | |||
PAYMENT_METHOD_TYPE | Integer | Maximum | |||
PAYMENT_ACCOUNT_NUMBER | String | 19 | |||
CREATED_BY | Integer | Maximum | |||
CREATION_DATE | DATE | Date | |||
LAST_UPDATED_BY | Integer | Maximum | |||
LAST_UPDATE_DATE | DATE | Date |
Hints for creating the TRANSACTION_REVERSAL
table. →
This provides a couple tricks that save some typing.
Oracle Trick and Technique
The following shows you how to get key definition syntax from the Oracle data dictionary. You can find the column definitions by getting the syntax for the TRANSACTION
table, and the external table components from the definition of the TRANSACTION_UPLOAD
table.
1 2 3 4 5 6 7 8 9 10 11 12 | -- Set environment variables. SET LONG 100000 SET PAGESIZE 0 -- Set a local variable of a character large object (CLOB). VARIABLE ddl_text CLOB -- Get the internal DDL command for the TRANSACTION table from the data dictionary. SELECT dbms_metadata.get_ddl('TABLE','TRANSACTION') FROM dual; -- Get the internal DDL command for the external TRANSACTION_UPLOAD table from the data dictionary. SELECT dbms_metadata.get_ddl('TABLE','TRANSACTION_UPLOAD') FROM dual; |
You can move the table from the Oracle External TRANSACTION_REVERSAL
table into the TRANSACTION
table with this trick:
1 2 3 4 | -- Move the data from TRANSACTION_REVERSAL to TRANSACTION. INSERT INTO TRANSACTION (SELECT <column_list> FROM transaction_reversal); |
You should find that you have 1,170 rows in the TRANSACTION_REVERSAL
table. After you insert them into the TRANSACTION
table, run the following queries and compare results.
Run this query:
1 2 3 4 5 6 7 8 9 10 11 12 | COLUMN "Debit Transactions" FORMAT A20 COLUMN "Credit Transactions" FORMAT A20 COLUMN "All Transactions" FORMAT A20 -- Check current contents of the model. SELECT 'SELECT record counts' AS "Statement" FROM dual; SELECT LPAD(TO_CHAR(c1.transaction_count,'99,999'),19,' ') AS "Debit Transactions" , LPAD(TO_CHAR(c2.transaction_count,'99,999'),19,' ') AS "Credit Transactions" , LPAD(TO_CHAR(c3.transaction_count,'99,999'),19,' ') AS "All Transactions" FROM (SELECT COUNT(*) AS transaction_count FROM transaction WHERE transaction_account = '111-111-111-111') c1 CROSS JOIN (SELECT COUNT(*) AS transaction_count FROM transaction WHERE transaction_account = '222-222-222-222') c2 CROSS JOIN (SELECT COUNT(*) AS transaction_count FROM transaction) c3; |
You should get the following results.
Debit Transactions Credit Transactions All Transactions -------------------- -------------------- -------------------- 4,681 1,170 5,851 |
- [10 points] Create the following transformation report by a
CROSS JOIN
between theTRANSACTION
andCALENDAR
tables. While it is possible to perform this task when the accounting periods are calendar months with only theTRANSACTION
table, that coincidence isn’t always the case. Therefore, this presents an opportunity to reinforce a non-equijoin range query.
Implementation Note: This is an ad hoc (run anytime report) that shows rental income, expense, and the total (rental income – rental expense). A zero is returned when there’s no income or expense in a given calendar period (month, quarter, or year-to-date).
Business Rule: Rental income are those rows in the TRANSACTION
table that have a PAYMENT_ACCOUNT_NUMBER
of 111-111-111-111
, and rental return income are those rows in the TRANSACTION
table that have a PAYMENT_ACCOUNT_NUMBER
of 222-222-222-222
.
System Logic: The CASE
statement inside of a SUM
function call on the TRANSACTION_DATE
column allows you to return only qualifying TRANSACTION_AMOUNT
column values in the aggregated sum.
The desired layout is noted below in the color formatted table.
Annual Financial Report | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Transaction | Jan | Feb | Mar | FQ1 | Apr | May | Jun | FQ2 | Jul | Aug | Sep | FQ3 | Oct | Nov | Dec | FQ4 | YTD |
Income | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn |
Expense | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn |
Total | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn | n,nnn.nn |
Hint →
This shows you how to apply the aggregation syntax for a single month and year. You should also check the lookup functions for quarters and year-to-date transformation columns.
You should be able to extend this behavior to fulfill most of this steps’ requirements. However, you’ll need to replicate a number of components, label them respectively as the month, quarter, or year-to-date; and then wrap this as an inline view.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | SELECT CASE WHEN t.transaction_account = '111-111-111-111' THEN 'Debit' WHEN t.transaction_account = '222-222-222-222' THEN 'Credit' END AS "TRANSACTION_ACCOUNT" , CASE WHEN t.transaction_account = '111-111-111-111' THEN 1 WHEN t.transaction_account = '222-222-222-222' THEN 2 END AS "SORTKEY" , LPAD(TO_CHAR (SUM(CASE WHEN EXTRACT(MONTH FROM transaction_date) = 1 AND EXTRACT(YEAR FROM transaction_date) = 2009 THEN CASE WHEN cl.common_lookup_type = 'DEBIT' THEN t.transaction_amount ELSE t.transaction_amount * -1 END END),'99,999.00'),10,' ') AS "JANUARY" FROM transaction t INNER JOIN common_lookup cl ON t.transaction_type = cl.common_lookup_id WHERE cl.common_lookup_table = 'TRANSACTION' AND cl.common_lookup_column = 'TRANSACTION_TYPE' GROUP BY CASE WHEN t.transaction_account = '111-111-111-111' THEN 'Debit' WHEN t.transaction_account = '222-222-222-222' THEN 'Credit' END , CASE WHEN t.transaction_account = '111-111-111-111' THEN 1 WHEN t.transaction_account = '222-222-222-222' THEN 2 END; |
The numbers that let you verify the accuracy of your query are:
Transaction Jan Feb Mar F1Q Apr May Jun F2Q Jul Aug Sep F3Q Oct Nov Dec F4Q YTD --------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ Debit 2,520.00 4,029.00 5,067.00 11,616.00 4,653.00 2,091.00 1,140.00 7,884.00 2,268.00 2,115.00 2,073.00 6,456.00 3,090.00 2,949.00 2,208.00 8,247.00 34,203.00 Credit -651.00 -996.00 -1,326.00 -2,973.00 -1,125.00 -522.00 -282.00 -1,929.00 -570.00 -522.00 -549.00 -1,641.00 -825.00 -786.00 -567.00 -2,178.00 -8,721.00 Total 1,869.00 3,033.00 3,741.00 8,643.00 3,528.00 1,569.00 858.00 5,955.00 1,698.00 1,593.00 1,524.00 4,815.00 2,265.00 2,163.00 1,641.00 6,069.00 25,482.00 |
The “Oracle Tip and Technique” Portion tells you to move transaction into transaction_reversal, we want to do the opposite.
Sam Graham
4 Dec 14 at 9:26 pm
Sam, you’re right. It’s fixed now.
michaelmclaughlin
21 Dec 14 at 5:24 pm