Creating stored procedure to insert new rows into a table - sql

I am trying to create a stored procedure which fulfill the following question,
Write a stored procedure called event_registration which handles the participant's entry for an event. When a participant registers for an event, they may also choose to create or join a group.
Your procedure must take four input parameters:
participant number
exhibition date
event type description
group name.
The procedure must:
check if the input exhibition date and event name are valid
check if the participants wants to create/join a group (ie. they provide a group name) and, if provided, whether the group name exists for the input exhibition:
If the group does not exist then the procedure should add a new group and assign this participant as the group leader, or
If the group exists then the procedure should add the participant into the existing group
So the below are my tables:
CREATE TABLE group
(
group_id NUMBER(3) NOT NULL,
group_name VARCHAR2(30) NOT NULL,
exhibition_date DATE NOT NULL,
group_no_members NUMBER(2) NOT NULL,
event_id NUMBER(6) NOT NULL,
entry_no NUMBER(5) NOT NULL,
char_id NUMBER(3)
);
CREATE TABLE event
(
event_id NUMBER(6) NOT NULL,
exhibition_date DATE NOT NULL,
eventtype_code CHAR(3) NOT NULL,
event_starttime DATE NOT NULL
);
CREATE TABLE eventtype
(
eventtype_code CHAR(3) NOT NULL,
eventtype_desc VARCHAR2(50) NOT NULL
);
CREATE TABLE exhibition
(
exhibition_date DATE NOT NULL,
exhibition_name VARCHAR2(50) NOT NULL,
exhibition_director VARCHAR2(50) NOT NULL,
exhibition_location VARCHAR2(50) NOT NULL
);
CREATE TABLE entry
(
event_id NUMBER(6) NOT NULL,
entry_no NUMBER(5) NOT NULL,
entry_starttime DATE,
entry_finishtime DATE,
part_no NUMBER(5) NOT NULL,
group_id NUMBER(3),
char_id NUMBER(3)
);
And this is my procedure:
CREATE OR REPLACE PROCEDURE event_registration
(new_part_no IN NUMBER,
new_exhibition_date IN DATE,
new_eventtype_desc IN VARCHAR2,
new_group_name IN VARCHAR2,
output OUT VARCHAR2)
AS
exhibition_date_and_event_found NUMBER; group_found NUMBER;
BEGIN
SELECT COUNT(*)
INTO exhibition_date_and_event_found
FROM event
NATURAL JOIN eventtype
WHERE exhibition_date = new_exhibition_date
AND eventtype_desc = new_eventtype_desc;
IF (exhibition_date_and_event_found = 0) THEN
output := 'Invalid exhibition date/This exhibition does not have this event type';
ELSE
IF(new_group_name != NULL) THEN
SELECT COUNT(*) INTO group_found FROM group NATURAL JOIN exhibition WHERE group_name = new_group_name AND exhibition_date = new_exhibition_date;
IF(group_found = 0) THEN
INSERT INTO group VALUES ((SELECT COUNT(*)+1 FROM group), new_group_name, TO_DATE(new_exhibition_date, 'DD/MM/YYYY'), 1, (SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date,'DD/MM/YYYY')), (SELECT MAX(entry_no)+1 FROM entry WHERE event_id = (SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY'))), NULL);
INSERT INTO entry VALUES ((SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY')), (SELECT MAX(entry_no)+1 FROM entry WHERE event_id = (SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY'))), NULL, NULL, new_part_no, (SELECT group_id FROM group WHERE group_name = new_group_name), NULL);
ELSE --group already exist
--update the group member number by 1
UPDATE group
SET group_no_members = group_no_members + 1
WHERE group_name = new_group_name;
INSERT INTO entry VALUES ((SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY')), (SELECT MAX(entry_no)+1 FROM entry WHERE event_id = (SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY'))), NULL, NULL, new_part_no, (SELECT group_id FROM group WHERE group_name = new_group_name), NULL);
END IF;
ELSE
INSERT INTO entry VALUES ((SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY')), (SELECT MAX(entry_no)+1 FROM entry WHERE event_id = (SELECT event_id FROM event NATURAL JOIN eventtype WHERE eventtype_desc = new_eventtype_desc AND exhibition_date = TO_DATE(new_exhibition_date, 'DD/MM/YYYY'))), NULL, NULL, new_part_no, NULL, NULL);
END IF;
END IF;
END;
/
The procedure is not done yet but I think it is good enough to be compiled, but when I run it, it gives out errors like
Procedure EVENT_REGISTRATION compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
12/9 PL/SQL: SQL Statement ignored
12/21 PL/SQL: ORA-00947: not enough values
18/9 PL/SQL: SQL Statement ignored
18/21 PL/SQL: ORA-00947: not enough values
21/9 PL/SQL: SQL Statement ignored
21/21 PL/SQL: ORA-00947: not enough values
Errors: check compiler log
Can anybody help me with this? Thank you in advance!

Use constraints on your tables (primary keys, foreign keys, etc.).
Use sequences for primary key values (NEVER use SELECT COUNT(*) + 1 FROM ... to generate ids as you are likely to get duplicates on a parallel system).
If you use constraints then you don't need to check that the exhibition date and event (exhibition?) name are correct as, if they are not, the constraint will raise an exception when you try to against a non-existent relationship.
NEVER use INSERT INTO table_name VALUES (...), you should always explicitly name the columns you are inserting into using:
INSERT INTO table_name (col1, col2, col3) VALUES (value1, value2, value3);
Do not keep using the same query over-and-over to find the event_id. Find it once and store it in a PL/SQL variable and then use the PL/SQL variable the next time.
GROUP is a reserved word; do not use it as an identifier.
You cannot compare a value to NULL using value != NULL as NULL is never equal or not-equal to anything else; you need to use value IS NOT NULL.
Make sure you do not have cyclic referential constraints in your tables (i.e. GROUP has an entry_no which refers to the entry table and the entry table has a group_id column that refers to the GROUP table. You do not need both and when you put constraints in then you will get a cycle.)
Something like:
CREATE TABLE exhibition
(
exhibition_date DATE
PRIMARY KEY
NOT NULL,
exhibition_name VARCHAR2(50)
NOT NULL,
exhibition_director VARCHAR2(50)
NOT NULL,
exhibition_location VARCHAR2(50)
NOT NULL
);
CREATE TABLE eventtype
(
eventtype_code CHAR(3)
PRIMARY KEY
NOT NULL,
eventtype_desc VARCHAR2(50)
NOT NULL
);
CREATE TABLE event
(
event_id NUMBER(6)
NOT NULL
PRIMARY KEY,
exhibition_date REFERENCES exhibition(exhibition_date)
NOT NULL,
eventtype_code REFERENCES eventtype(eventtype_code)
NOT NULL,
event_starttime DATE
NOT NULL
);
CREATE TABLE "GROUP"
(
group_id NUMBER(3)
NOT NULL
PRIMARY KEY,
group_name VARCHAR2(30)
UNIQUE
NOT NULL,
group_no_members NUMBER(2)
NOT NULL,
event_id REFERENCES event(event_id)
NOT NULL,
char_id NUMBER(3)
);
CREATE TABLE entry
(
event_id REFERENCES event(event_id)
NOT NULL,
entry_no NUMBER(5)
PRIMARY KEY
NOT NULL,
entry_starttime DATE,
entry_finishtime DATE,
part_no NUMBER(5)
NOT NULL,
group_id NUMBER(3)
REFERENCES "GROUP"(group_id),
char_id NUMBER(3)
);
Then:
CREATE SEQUENCE group_seq;
CREATE SEQUENCE entry_seq;
Then:
CREATE OR REPLACE PROCEDURE event_registration
(new_part_no IN NUMBER,
new_exhibition_date IN DATE,
new_eventtype_desc IN VARCHAR2,
new_group_name IN VARCHAR2,
output OUT VARCHAR2)
AS
v_event_id EVENT.EVENT_ID%TYPE;
v_group_id "GROUP".GROUP_ID%TYPE;
BEGIN
SELECT e.event_id
INTO v_event_id
FROM event e
INNER JOIN eventtype et
ON (e.eventtype_code = et.eventtype_code)
WHERE exhibition_date = new_exhibition_date
AND eventtype_desc = new_eventtype_desc;
IF new_group_name IS NOT NULL THEN
MERGE INTO "GROUP" g
USING DUAL
ON (g.group_name = new_group_name)
WHEN MATCHED THEN
UPDATE
SET group_no_members = group_no_members + 1
WHEN NOT MATCHED THEN
INSERT (
group_id,
group_name,
group_no_members,
event_id,
char_id
) VALUES (
GROUP_SEQ.NEXTVAL,
new_group_name,
1,
v_event_id,
NULL
);
SELECT group_id
INTO v_group_id
FROM "GROUP"
WHERE group_name = new_group_name;
END IF;
INSERT INTO entry (
event_id,
entry_no,
entry_starttime,
entry_finishtime,
part_no,
group_id,
char_id
)VALUES (
v_event_id,
entry_seq.NEXTVAL,
NULL,
NULL,
new_part_no,
v_group_id,
NULL
);
EXCEPTION
WHEN NO_DATA_FOUND THEN
output := 'Invalid exhibition date/This exhibition does not have this event type';
END;
/
db<>fiddle here

Related

I am trying to create a procedure in oracle pl/sql but cant really put in the exact logic for what I am trying to do

When it takes input , email is given and all other parameters are null it should show all records of that email. Similarly with other three input paramters.
If all inputs are null then it should show all records of the student table.
create or replace procedure get_student_records(
pis_email in varchar2,
pis_rollno in number,
pis_dept in varchar,
pi_class_id in number
)
IS
begin
end get_student_records;
Tables to be accessed :
CREATE TABLE student (
s_id NUMBER(10) NOT NULL,
s_rollno NUMBER(10) NOT NULL,
s_name VARCHAR2(20) NOT NULL,
s_dept VARCHAR2(10),
s_email VARCHAR2(25),
class_id NUMBER(10),
CONSTRAINT student_pk PRIMARY KEY ( s_rollno ),
CONSTRAINT fk_class FOREIGN KEY ( class_id )
REFERENCES class ( class_id )
);
CREATE TABLE class (
class_id NUMBER(10) NOT NULL,
class_name VARCHAR2(10) NOT NULL,
dept_id NUMBER(10),
CONSTRAINT class_pk PRIMARY KEY ( class_id ),
CONSTRAINT fk_depts FOREIGN KEY ( dept_id )
REFERENCES dept ( dept_id )
);
CREATE TABLE dept (
dept_id NUMBER(10) NOT NULL,
dept_name VARCHAR2(50) NOT NULL,
CONSTRAINT depts_pk PRIMARY KEY ( dept_id )
);
There is a trick you can use -- lets say in_email, in_name are parameters and the fields are name and email -- the query looks like this:
SELECT *
FROM table as t
WHERE COALESCE(in_name,t.name) = name AND COALESCE(in_email,t.email) = email
The way this works -- when the parameter is null the statement is true (so all are found -> it is a wildcard. When there is a value, it only matches on the exact value.

Argument of AND must not return a set when used with BETWEEN in a check constraint

I am encountering the error "argument of AND must not return a set" from the AND in the check constraint of the below table.
CREATE TABLE loan (
id SERIAL PRIMARY KEY,
copy_id INTEGER REFERENCES media_copies (copy_id),
account_id INT REFERENCES account (id),
loan_date DATE NOT NULL,
expiry_date DATE NOT NULL,
return_date DATE,
CONSTRAINT max_student_concurrent_loans CHECK(
CurrentStudentLoansCount() BETWEEN 1 AND 7
)
);
The implementation of CurrentStudentLoansCount() is shown below.
CREATE OR REPLACE FUNCTION CurrentStudentLoansCount()
RETURNS TABLE(accid BIGINT) AS $$
BEGIN
RETURN QUERY
SELECT COUNT(*)
FROM loan
WHERE account_id IN (SELECT id FROM student)
AND return_date IS NULL
GROUP BY account_id;
END
$$ LANGUAGE PLPGSQL;
Why am I running into this error and how can I work around it?
For context, the below figure displays my database schema.
Your function returns a table with multiple rows so you can't use that for a BETWEEN condition. Presumably you just want that value for the account_id of that row of the table (not for all account_ids).
So change the function to return a single value by passing it the account_id. And you also don't need PL/pgSQL for this:
CREATE OR REPLACE FUNCTION currentstudentloanscount(p_account_id integer)
RETURNS bigint
as
$$
SELECT COUNT(*)
FROM loan
WHERE account_id = p_account_id
AND return_date IS NULL;
$$ LANGUAGE sql;
And change your table definition to:
CREATE TABLE loan (
id SERIAL PRIMARY KEY,
copy_id INTEGER REFERENCES media_copies (copy_id),
account_id INT REFERENCES account (id),
loan_date DATE NOT NULL,
expiry_date DATE NOT NULL,
return_date DATE,
CONSTRAINT max_student_concurrent_loans
CHECK(currentstudentloanscount(account_id) BETWEEN 1 AND 7)
);

Ignoring a column in select query but need to use as a join condition

Here i have this proc where i need to insert data into target table 4.In all these subqueries first_scan_issues/last_scan_issues/Prior_scan_issues where i need to join based on the scan_id but same time i should not use the scan_id in select query where the grouping result sets are splitting into more granularity.Even i tried with 'Partition by clause' it also gives more number of records. How can we avoid scan_id column and should use the same as join condition.
Target table 4
SOA_SECTOR VARCHAR2(100 CHAR)
SOA_REGION VARCHAR2(100 CHAR)
PROJECT NOT NULL VARCHAR2(256 CHAR)
SOLUTION VARCHAR2(256 CHAR)
FIRST_SCAN_ISSUE_CNT NOT NULL NUMBER(10)
FIRST_FILES_WITH_ISSUES_CNT NOT NULL NUMBER(10)
FIRST_SCAN_FILE_CNT NOT NULL NUMBER(10)
TOTAL_FILES_FOR_PROJECT_CNT NOT NULL NUMBER(10)
LAST_SCAN_ISSUE_CNT NOT NULL NUMBER(10)
LAST_FILES_WITH_ISSUES_CNT NOT NULL NUMBER(10)
LAST_SCAN_FILE_CNT NOT NULL NUMBER(10)
PRIOR_SCAN_ISSUE_CNT NOT NULL NUMBER(10)
PRIOR_FILE_WITH_ISSUES_CNT NOT NULL NUMBER(10)
PRIOR_SCAN_FILE_CNT NOT NULL NUMBER(10)
LOAD_DATE_TIME NOT NULL DATE
Proc
CREATE OR REPLACE PROCEDURE PROC AS
BEGIN
INSERT INTO table4
SELECT first_scan_issues.SOA_SECTOR,
first_scan_issues.SOA_REGION,
a.PROJECT,
a.SOLUTION,
first_scan_issues.CNT1,
first_scan_issues.CNT2,
file_scans.CNT7,
project_files_count.COUNT,
last_scan_issues.CNT3,
last_scan_issues.CNT4,
file_scans.CNT8,
prior_scan_issues.CNT5,
prior_scan_issues.CNT6,
file_scans.CNT9,
CURRENT_DATE
FROM( select PROJECT,SOLUTION,FIRST_SCAN_ID,LAST_SCAN_ID,PRIOR_SCAN_ID from table1 order by project
)a
LEFT OUTER JOIN
(
select SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID,
COUNT(DISTINCT ISSUE_ID) CNT3,
COUNT(DISTINCT FILE_ID) CNT4
from table2 group by SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID
) first_scan_issues on first_scan_issues.SCAN_ID = a.FIRST_SCAN_ID AND first_scan_issues.PROJECT =a.PROJECT
LEFT OUTER JOIN
(
select SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID,
COUNT(DISTINCT ISSUE_ID) CNT3,
COUNT(DISTINCT FILE_ID) CNT4
from table2 group by SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID
)last_scan_issues ON last_scan_issues.SCAN_ID = a.LAST_SCAN_ID AND last_scan_issues.PROJECT =a.PROJECT
LEFT OUTER JOIN
(
select SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID,
COUNT(DISTINCT ISSUE_ID) CNT3,
COUNT(DISTINCT FILE_ID) CNT4
from table2 group by SOA_SECTOR,SOA_REGION,PROJECT,SOLUTION,SCAN_ID
) prior_scan_issues ON PRIOR_scan_issues.SCAN_ID = a.PRIOR_SCAN_ID AND prior_scan_issues.PROJECT =a.PROJECT
LEFT OUTER JOIN
(
select project,solution, count(distinct FIRST_SCAN_ID) CNT7,
count(distinct LAST_SCAN_ID) CNT8,count(distinct PRIOR_SCAN_ID) CNT9
from table1 group by project,solution order by project
)file_scans ON file_scans.PROJECT=a.PROJECT
JOIN
(
SELECT PROJECT,SOLUTION,SOA_SECTOR,SOA_REGION,
COUNT(DISTINCT PATH) COUNT
FROM table3
GROUP BY PROJECT,SOLUTION,SOA_SECTOR,SOA_REGION
) project_files_count
ON project_files_count.PROJECT = a.PROJECT;
END;
CREATE TABLE table1 (
PROJECT VARCHAR2(256 CHAR) NOT NULL,
SOLUTION VARCHAR2(256 CHAR),
FIRST_SCAN_ID NUMBER(10) NOT NULL,
LAST_SCAN_ID NUMBER(10) NOT NULL,
PRIOR_SCAN_ID NUMBER(10) NOT NULL,
CONSTRAINT pk_tmp_first_last_scan_ids_id PRIMARY KEY (PROJECT)
);
CREATE TABLE table2
(
ISSUE_ID NUMBER(10)
CONSTRAINT RPT_ISSUE_SUMMARY_PK
PRIMARY KEY,
SOA_SECTOR VARCHAR2(128),
SOA_REGION VARCHAR2(128),
USERNAME VARCHAR2(128),
PROJECT VARCHAR2(256),
SOLUTION VARCHAR2(256),
PATH VARCHAR2(2048),
TIME DATE,
CATEGORY VARCHAR2(512),
TITLE VARCHAR2(512),
ISSUE_IMP VARCHAR2(256),
CLICKED NUMBER(3),
SCAN_ID NUMBER(10),
SESSION_ID NUMBER(10),
RULEPACK_RULE_ID NUMBER(10),
FILE_ID NUMBER(10),
FILE_INFO_ID NUMBER(10),
SCAN_YEAR_MON VARCHAR2(7),
SCAN_YEAR VARCHAR2(4),
SCAN_MONTH VARCHAR2(2),
LOAD_TIME DATE NOT NULL
);
CREATE TABLE table3
(
SOA_SECTOR VARCHAR2(128),
SOA_REGION VARCHAR2(128),
USERNAME VARCHAR2(128),
PROJECT VARCHAR2(256) NOT NULL,
SOLUTION VARCHAR2(256),
PATH VARCHAR2(2048) NOT NULL,
TIME DATE NOT NULL,
LOC NUMBER(10) NOT NULL,
SCAN_ID VARCHAR2(256),
SESSION_ID VARCHAR2(256),
FILE_ID VARCHAR2(256),
FILE_INFO_ID VARCHAR2(256),
SCAN_YEAR_MON VARCHAR2(7),
SCAN_YEAR VARCHAR2(7),
SCAN_MONTH VARCHAR2(7),
LOAD_DATE_TIME DATE NOT NULL,
CONSTRAINT rpt_scan_summary_pk PRIMARY KEY (SCAN_ID, FILE_ID)
)

How can this postgresql query return as table?

I am trying to call modules which in specific course but it returns as error: more than one row returned by a subquery used as an expression
Query:
CREATE OR REPLACE FUNCTION course_modules(_courseID integer)
RETURNS SETOF modules AS
$$
BEGIN
RETURN QUERY SELECT * FROM modules WHERE mod_id =(SELECT module_id from coursemodules WHERE course_id = _courseID);
END
$$
LANGUAGE 'plpgsql';
coursemodule table
CREATE TABLE coursemodules(
course_id integer references courses (id) ON DELETE CASCADE,
module_id integer references modules (mod_id) ON DELETE CASCADE
);
Modules Table
CREATE TABLE modules(
documents text NOT NULL,
mod_id serial primary key,
content text NOT NULL,
title varchar(50) NOT NULL
);
Course Table
CREATE TABLE courses(
finishDate Date,
description text NOT NULL,
duration varchar(50) NOT NULL,
startDate Date,
id serial primary key,
courseName varchar(50) NOT NULL
);
There is no restriction in the coursemodule table that a course could only have one module. Because of that the SELECT module_id from coursemodules WHERE course_id = _courseID subquery could return multiple lines.
If you change mod_id = (SELECT module_id from coursemodules WHERE course_id = _courseID)
to
mod_id IN (SELECT module_id from coursemodules WHERE course_id = _courseID).
It should work. Otherwise you have to add constraints to the coursemodule table.
This is a simple SQL syntax error. You're using
WHERE mod_id =
But you may have more than one row returning from the subquery. User IN:
WHERE mod_id IN

SQL Logic and Aggregate Issue

I have the following problem to solve in SQL :
d) A query that provides management information on take up of the various types of activities on offer. For each type of activity, the query should show the total number of individuals who took that type of activity and the average number of individuals taking each type of activity.
Here are my tables :
CREATE TABLE accommodations
(
chalet_number int PRIMARY KEY,
chalet_name varchar(40) NOT NULL,
no_it_sleeps number(2) NOT NULL,
indivppw number(4) NOT NULL
)
CREATE TABLE supervisors
(
supervisor_number int PRIMARY KEY,
supervisor_forename varchar(30) NOT NULL,
supervisor_surname varchar(30) NOT NULL,
mobile_number varchar(11) NOT NULL
)
CREATE TABLE visitors
(
visitor_ID int PRIMARY KEY,
group_ID int NOT NULL,
forename varchar(20) NOT NULL,
surname varchar(20) NOT NULL,
dob date NOT NULL,
gender varchar(1) NOT NULL
)
CREATE TABLE activities
(
activity_code varchar(10) PRIMARY KEY,
activity_title varchar(20) NOT NULL,
"type" varchar(20) NOT NULL
)
CREATE TABLE "groups"
(
group_ID int PRIMARY KEY,
group_leader varchar(20) NOT NULL,
group_name varchar(30)
number_in_group number(2) NOT NULL
)
CREATE TABLE bookings
(
group_ID int NOT NULL,
start_date date NOT NULL,
chalet_number int NOT NULL,
no_in_chalet number(2) NOT NULL,
start_date date NOT NULL,
end_date date NOT NULL,
CONSTRAINT bookings_pk PRIMARY KEY(group_ID, chalet_number));
CREATE TABLE schedule
(
schedule_ID int PRIMARY KEY,
activity_code varchar(10) NOT NULL,
time_of_activity number(4,2) NOT NULL,
am_pm varchar(2) NOT NULL,
"date" date NOT NULL
)
CREATE TABLE activity_bookings
(
visitor_ID int NOT NULL,
schedule_ID int NOT NULL,
supervisor_number int NOT NULL,
comments varchar(200),
CONSTRAINT event_booking_pk PRIMARY KEY(visitor_ID, schedule_ID));
ALTER TABLE visitors
ADD FOREIGN KEY (group_ID)
REFERENCES "groups"(group_ID)
ALTER TABLE Schedule
ADD FOREIGN KEY (activity_code)
REFERENCES activities(activity_code)
ALTER TABLE bookings
ADD FOREIGN KEY (group_ID)
REFERENCES "groups"(group_ID)
ALTER TABLE bookings
ADD FOREIGN KEY (chalet_number)
REFERENCES accommodations(chalet_number)
ALTER TABLE activity_bookings
ADD FOREIGN KEY (visitor_ID)
REFERENCES visitors(visitor_ID)
ALTER TABLE activity_bookings
ADD FOREIGN KEY (schedule_ID)
REFERENCES schedule(schedule_ID)
ALTER TABLE activity_bookings
ADD FOREIGN KEY (supervisor_number)
REFERENCES supervisors(supervisor_number)
I have the following solution:
SELECT activities."type", 'overalltotal' AS OT, ('overalltotal' / 'activities') AS AVG
FROM activities, schedule
WHERE 'overalltotal' = (SELECT SUM(COUNT(schedule_ID))
FROM activities, schedule
WHERE schedule.activity_code = activities.activity_code
GROUP BY activities."type"
)
AND 'activities' = (SELECT COUNT(DISTINCT activities."type")
FROM activities
)
AND schedule.activity_code = activities.activity_code
GROUP BY activities."type";
I have implemented sample data and code to check the variables above:
SELECT SUM(COUNT(schedule_ID))
FROM activities, schedule
WHERE schedule.activity_code = activities.activity_code
GROUP BY activities."type";
Result : 20
SELECT COUNT(DISTINCT activities."type")
FROM activities;
Result : 5
However when running the code :
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause:
*Action:
EDIT:
Using Dave's Code i have the following output:
Snowboarding 15
sledding 19
Snowmobiling 6
Ice Skating 5
Skiing 24
How would i do the final part of the question?
and the average number of individuals taking each type of activity.
You must use double quotes around column names in Oracle, not single quotes. For example, "overalltotal". Single quotes are for text strings, which is why you're getting an invalid number error.
EDIT: This is probably the type of query you want to use:
SELECT activities."type", COUNT(*) AS total, COUNT(*)/(COUNT(*) OVER ()) AS "avg"
FROM activities a
JOIN schedule s ON a.activity_code=s.activity_code
JOIN activity_bookings ab ON s.schedule_ID=ab.schedule_ID
GROUP BY activities."type";
Basically, because each activity booking has one visitor id, we want to get all the activity bookings for each activity. We have to go through schedule to do that. They we group the rows by the activity type and count how many activity bookings we have for each type.