Oracle SQL Average query - sql

I need to do an average median with Oracle. I have this:
SELECT V.Id_Aeropuerto_Destino AS Id_Aeropuerto, C.Nombre AS Ciudad_Destino, A.nombre AS Aeropuerto,
(SELECT SUM((TO_NUMBER(V.Retraso_Salida,'99999999D99','nls_numeric_characters=''.,''')) +
(TO_NUMBER(V.Retraso_Llegada,'99999999D99','nls_numeric_characters=''.,''')))
FROM Vuelo V
WHERE V.Id_Aeropuerto_Destino=Id_Aeropuerto) Retraso_Total
FROM Ciudad C, Aeropuerto A, Vuelo V
WHERE V.Id_Aeropuerto_Destino=A.Id_Aeropuerto AND A.Ciudad = C.Id_Ciudad;
This calculates the total delay of a number of flights ("Retraso_Total"). Now I need to do an AVG from "Retraso_Total", to get ("Retraso_Total" / number of flights) -> Retraso_Medio, something like this:
SELECT V.Id_Aeropuerto_Destino AS Id_Aeropuerto, C.Nombre AS Ciudad_Destino, A.nombre AS Aeropuerto,
(SELECT AVG SUBQUERY) Retraso_Medio,
(SELECT SUM((TO_NUMBER(V.Retraso_Salida,'99999999D99','nls_numeric_characters=''.,''')) +
(TO_NUMBER(V.Retraso_Llegada,'99999999D99','nls_numeric_characters=''.,''')))
FROM Vuelo V
WHERE V.Id_Aeropuerto_Destino=Id_Aeropuerto) Retraso_Total
FROM Ciudad C, Aeropuerto A, Vuelo V
WHERE V.Id_Aeropuerto_Destino=A.Id_Aeropuerto AND A.Ciudad = C.Id_Ciudad;
I try with this:
SELECT AVG(SUM((TO_NUMBER(V.Retraso_Salida,'99999999D99','nls_numeric_characters=''.,''')) +
(TO_NUMBER(V.Retraso_Llegada,'99999999D99','nls_numeric_characters=''.,'''))))
FROM Vuelo V
WHERE V.Id_Aeropuerto_Destino=Id_Aeropuerto
GROUP BY V.Id_Aeropuerto_Destino) Retraso_Medio
But this subquery doesn't work.
How I can do that (all in the same query)?
Thanks!!
Table Vuelo (Flight) has (id_plane, id_origin_airport, id_destiny_airport, id_company, departure hour, arrival hour, departure delay, arrival delay, date, canceled, passengers, milles:
CREATE TABLE Vuelo(
Id_Avion number(4),
Id_Aeropuerto_Origen number(5),
Id_Aeropuerto_Destino number(5),
Id_Aerolinea varchar(2),
Hora_Salida number(4),
Hora_Llegada number(4),
Retraso_Salida varchar(5),
Retraso_Llegada varchar(5),
Fecha varchar(10),
Cancelado varchar(3) NOT NULL,
Pasajeros varchar(10) NOT NULL,
Distancia varchar(10) NOT NULL,
CONSTRAINT pk_Vuelo PRIMARY KEY(Id_Avion, Id_Aeropuerto_Origen, Fecha, Hora_salida),
CONSTRAINT fk_Avion FOREIGN KEY(Id_Avion) REFERENCES Avion(Id_Avion),
CONSTRAINT fk_Aeropuerto_Origen FOREIGN KEY(Id_Aeropuerto_Origen) REFERENCES Aeropuerto(Id_Aeropuerto),
CONSTRAINT fk_Aeropuerto_Destino FOREIGN KEY(Id_Aeropuerto_Destino) REFERENCES Aeropuerto(Id_Aeropuerto),
CONSTRAINT fk_Aerolinea FOREIGN KEY(Id_Aerolinea) REFERENCES Aerolinea(Id_Aerolinea),
CONSTRAINT fk_Fecha FOREIGN KEY(Fecha) REFERENCES Fecha(Id_Fecha)
);
Table Ciudad (City) has id_city, name, latitude, longitude, population, timezone:
CREATE TABLE Ciudad(
Id_Ciudad number(7),
Nombre varchar(80) NOT NULL,
Latitud varchar(15) NOT NULL,
Longitud varchar(15) NOT NULL,
Habitantes number(10) NOT NULL,
Timezone varchar(80) NOT NULL,
CONSTRAINT pk_Ciudad PRIMARY KEY(Id_Ciudad)
);
Table Aeropuerto (Airport) has id_airport, name, code, id_city, state, state_code:
CREATE TABLE Aeropuerto(
Id_Aeropuerto number(5),
Nombre varchar(80) NOT NULL,
Codigo varchar(4) NOT NULL,
Ciudad number(5) NOT NULL,
Estado varchar(80) NOT NULL,
Codigo_Estado varchar(4) NOT NULL,
CONSTRAINT pk_Aeropuerto PRIMARY KEY(Id_Aeropuerto),
CONSTRAINT fk_Ciudad FOREIGN KEY(Ciudad) REFERENCES Ciudad(Id_Ciudad)
);

From your comments it seems you want to calculate a MEAN rather than a MEDIAN as your question's opening line says.
This is quite simple. The Oracle AVG() function calculates the mean for us, without the need to derive totals and counts. Obviously it's still messy, due to the casting because table uses strings to store numeric values.
An average is an aggregate function, so we need to group by the non-aggregate columns. In your example that means the destination airport ID, City and Name. So this should work for you:
SELECT V.Id_Aeropuerto_Destino AS Id_Aeropuerto
, C.Nombre AS Ciudad_Destino
, A.nombre AS Aeropuerto
, AVG((TO_NUMBER(V.Retraso_Salida,'99999999D99','nls_numeric_characters=''.,''')) +
(TO_NUMBER(V.Retraso_Llegada,'99999999D99','nls_numeric_characters=''.,''')))
as "Retraso_Total"
FROM Vuelo V
join Aeropuerto A
on V.Id_Aeropuerto_Destino=A.Id_Aeropuerto
join Ciudad C
on A.Ciudad = C.Id_Ciudad
group by V.Id_Aeropuerto_Destino
, C.Nombre
, A.nombre
/

Related

Multiply columns and then sum rows: Oracle SQL

I'm trying to make a query in Oracle SQL Developer that must show the customer who has spend the biggest amount of money. So I have 4 tables: Cliente(Customer), Orden(Sale), Producto(Product) and a junction table to break many to many relationship between Orden and Producto.
CREATE TABLE Cliente(
id_cliente INT NOT NULL PRIMARY KEY,
Nombre VARCHAR(40) NOT NULL,
Apellido VARCHAR(40) NOT NULL,
Direccion VARCHAR(100) NOT NULL,
Telefono INT NOT NULL,
Tarjeta INT NOT NULL,
Edad INT NOT NULL,
Salario INT NOT NULL,
Genero VARCHAR(5) NOT NULL,
id_pais INT NOT NULL,
CONSTRAINT fk_cliente_pais FOREIGN KEY(id_pais) REFERENCES Pais(id_pais)
);
CREATE TABLE Producto(
id_producto INT NOT NULL PRIMARY KEY,
Nombre VARCHAR(40) NOT NULL,
Precio DECIMAL(10,2) NOT NULL,
id_categoria INT NOT NULL,
CONSTRAINT fk_categoria FOREIGN KEY(id_categoria) REFERENCES Categoria(id_categoria)
)
CREATE TABLE Orden(
id_orden INT NOT NULL,
linea_orden INT NOT NULL,
fecha_orden DATE NOT NULL,
id_cliente INT NOT NULL,
id_vendedor INT NOT NULL,
id_producto INT NOT NULL,
cantidad INT NOT NULL,
CONSTRAINT fk_orden_cliente FOREIGN KEY(id_cliente) REFERENCES Cliente(id_cliente),
CONSTRAINT fk_orden_vendedor FOREIGN KEY(id_vendedor) REFERENCES Vendedor(id_vendedor),
CONSTRAINT fk_orden_producto FOREIGN KEY(id_producto) REFERENCES Producto(id_producto),
CONSTRAINT pk_orden PRIMARY KEY(id_orden, linea_orden)
);
DROP TABLE Detalle;
CREATE TABLE Detalle(
id_detalle INT GENERATED ALWAYS AS IDENTITY,
id_producto INT NOT NULL,
id_orden INT NOT NULL,
linea_orden INT NOT NULL,
precio INT NOT NULL,
cantidad INT NOT NULL,
CONSTRAINT DETALLE_PRODUCTO
FOREIGN KEY (id_producto)
REFERENCES Producto (id_producto),
CONSTRAINT DETALLE_ORDEN
FOREIGN KEY (id_orden, linea_orden)
REFERENCES Orden (id_orden, linea_orden),
CONSTRAINT DETALLE_pk PRIMARY KEY(id_detalle, id_producto, id_orden)
);
On Table Detalle: precio (price), cantidad(quantity)
So I'm trying to get the Maximum total amount that a Customer has purchased by this query:
SELECT Cl.id_cliente, Cl.Nombre, Cl.Apellido,SUM( Detalle.precio * Detalle.cantidad) AS TOTAL
FROM Orden
INNER JOIN Cliente Cl ON Cl.id_cliente = Orden.id_cliente
INNER JOIN Detalle ON Detalle.id_orden = Orden.id_orden
GROUP BY Cl.id_cliente, Cl.Nombre, Cl.Apellido
ORDER BY TOTAL DESC;
But in the result, the TOTAL exceeds a lot from the right result, since I have another file with the result it should show.
I rewritten your query:
Select Cl.id_cliente, Cl.Nombre, Cl.Apellido,TOTAL
from(
SELECT Orden.id_cliente, SUM( Detalle.precio * Detalle.cantidad) AS TOTAL
FROM Detalle
JOIN Orden ON Detalle.id_orden = Orden.id_orden
GROUP BY Orden.id_cliente
) Orden
JOIN Cliente Cl ON Cl.id_cliente = Orden.id_cliente
ORDER BY TOTAL DESC
;
The data from details is summed multiple times, so calaculate them before joining
SELECT Cl.id_cliente, Cl.Nombre, Cl.Apellido,SUM(TOTAL ) AS TOTAL
FROM Orden
INNER JOIN Cliente Cl ON Cl.id_cliente = Orden.id_cliente
INNER JOIN (SELECT id_orden, SUM( Detalle.precio * Detalle.cantidad) AS TOTAL FROM Detalle GROUP BY id_orden) Detalle ON Detalle.id_orden = Orden.id_orden
GROUP BY Cl.id_cliente, Cl.Nombre, Cl.Apellido
ORDER BY TOTAL DESC;

SQL NEWBIE, LIKE CLAUSE

I'm new to SQL could someone correct me this query ?!
CREATE TABLE AVION
(
AV int IDENTITY(100, 1) PRIMARY KEY,
AVMARQUE varchar(30) NOT NULL,
AVTYPE varchar(30) NOT NULL,
CAP int CHECK (CAP BETWEEN 100 AND 600),
LOC varchar(30)
)
CREATE TABLE PILOTE
(
PIL int IDENTITY(1,1) PRIMARY KEY,
PILNOM varchar(30) NOT NULL,
ADR varchar(30)
)
CREATE TABLE VOLE
(
VOL varchar(5) PRIMARY KEY CHECK(VOL LIKE 'IT'[1,9][0,9][0,9]),
PIL int FOREIGN KEY REFERENCES PILOTE(PIL),
AV int FOREIGN KEY REFERENCES AVION(AV),
VD varchar(30) NOT NULL,
VA varchar(30) NOT NULL,
HD TIME CHECK (HD BETWEEN '00:00' AND '23:59'),
HA TIME CHECK (HA BETWEEN '00:00' AND '23:59')
)
VOL is a string with 5 characters that start with 'IT' and the rest are numbers first number is different then 0
PIL FOREIGN KEY FROM PILOTE TABLE
AV FOREIGN KEY FROM AVION TABLE
VD is the departure city
VA is the destination city
HD is the departure time
HV is the arrival time
It might be as simple as moving the quotes. Try:
LIKE 'IT[1,9][0,9][0,9]'

Bill Calculation using SQL

I've having some problems as I'm trying to calculate the total amount for a consumption.
so for example:
for the first 20 watt is charged at 0.40
for the next 20 watt is charged at 0.80
and 0.90 for each watt in excess of 20 watt
I've tried doing something on my own but the calculation is wrong and is there any way to optimize the query as i do not wish to do the calculation at the main select statement. is subquery a better option?
I'm using Oracle as DB engine
SELECT CustomerName, previousRead, newRead, newRead-previousRead AS Consumption,
(((newRead-previousRead-100)*FR)+((newRead-previousRead-200)*SR)+((newRead-previousRead-200)/200)*TR)as TotalBill
FROM (
SELECT C.firstName||''||C.lastName as CustomerName, R.newReading previousRead,
lead(R.newReading) OVER (PARTITION BY R.meterID ORDER BY R.dateVisited) AS newRead, B.firstconsumptionRate as FR,
B.secondconsumptionRate as SR, B.firstconsumptionRate as TR
FROM reading R, serviceaddress S, electricmeter W, customer C, rate A, nonresidentialrate B
WHERE W.meterID = S.meterID
AND R.meterID = W.meterID
AND A.rateID = S.rateID
AND B.rateID = A.rateID
AND C.custID = S.custID
AND C.custType = 'Non-residential'
AND r.datevisited >= TO_DATE('01-06-2014','DD-MM-YYYY')
AND r.datevisited < TO_DATE('31-07-2014','DD-MM-YYYY')
)where newRead is not null;
Table
CREATE TABLE Customer(
custID INTEGER NOT NULL,
firstName CHAR(25) NOT NULL,
lastName CHAR(25) NOT NULL,
NRIC CHAR(9) NOT NULL,
custType CHAR(25) NOT NULL,
badStatus CHAR(25) Default 'Good',
CONSTRAINT cust_Pkey PRIMARY KEY (custID),
CONSTRAINT cust_type CHECK (custType IN ('Residential', 'Non-residential')),
CONSTRAINT custBadStatus_type CHECK (badStatus IN ('Late Payment', 'Non Payment', 'Good'))
);
CREATE TABLE Reading (
readingID INTEGER NOT NULL,
meterID INTEGER NOT NULL,
dateVisited DATE NOT NULL,
newReading NUMBER(10,0) NOT NULL,
CONSTRAINT reading_Pkey PRIMARY KEY (readingID),
CONSTRAINT reading_AltKey UNIQUE (meterID, dateVisited),
CONSTRAINT reading_meterID_Fkey FOREIGN KEY (meterID) REFERENCES Meter (meterID),
CONSTRAINT checkReading CHECK (newReading > 0)
);
CREATE TABLE Rate (
rateID INTEGER NOT NULL,
rateApprDate DATE NOT NULL,
rateEffDate DATE NOT NULL,
rateType CHAR(25) NOT NULL,
CONSTRAINT rate_Pkey PRIMARY KEY (rateID),
CONSTRAINT rateType CHECK (rateType IN ('Residential', 'Non-residential')),
CONSTRAINT validDate CHECK (rateApprDate < rateEffDate),
);
CREATE TABLE NonResidentialRate (
rateID INTEGER NOT NULL,
firstconsumptionRate NUMBER(5,2) NOT NULL,
secondconsumptionRate NUMBER(5,2) NOT NULL,
thirdconsumptionRate NUMBER(5,2) NOT NULL,
CONSTRAINT nonResidentialRate_Pkey PRIMARY KEY (rateID),
CONSTRAINT nonResidentialRate_rateID_FK FOREIGN KEY (rateID) REFERENCES Rate (rateID)
);
CREATE TABLE ServiceAddress (
svcAddID INTEGER NOT NULL,
meterID INTEGER NOT NULL,
custID INTEGER NOT NULL,
rateID INTEGER NOT NULL,
street CHAR(30) NOT NULL,
city CHAR(35) NULL,
state CHAR(2) NULL,
zipPostalCode CHAR(9) NOT NULL,
CONSTRAINT serviceAddress_Pkey PRIMARY KEY (svcAddID),
CONSTRAINT serviceAddress_meterID_Fkey FOREIGN KEY (meterID) REFERENCES Meter (meterID),
CONSTRAINT serviceAddress_custID_Fkey FOREIGN KEY (custID) REFERENCES Customer (custID),
CONSTRAINT serviceAddress_rateID_Fkey FOREIGN KEY (rateID) REFERENCES Rate (rateID),
);
CREATE TABLE Meter (
meterID INTEGER NOT NULL,
SerialNum CHAR(30) NOT NULL,
installationDate DATE NOT NULL,
CONSTRAINT waterMeter_Pkey PRIMARY KEY (meterID),
CONSTRAINT waterMeter_Altkey UNIQUE (SerialNum)
);
The customer can be both of residential and non-residential and each of them has a service address. The meter is unique to each service address and the reading is stored in a different table.
There are 2 kinds of rates as well, their are different kind of rates for residential and nonresidential.
As for the reading, I did not create a new attribute for previous reading because it can be obtained tru the previous month reading
hope this makes my question clearer.
Here you go, you can give it a try..
SELECT CustomerName, previousRead, newRead, newRead-previousRead AS Consumption,
CASE WHEN newRead-previousRead <= 100
THEN (newRead-previousRead)*FR
WHEN newRead-previousRead <= 200
THEN 100*FR + (newRead-previousRead-100)*SR
WHEN newRead-previousRead > 200
THEN 100*FR + 100*SR + ((newRead-previousRead)-200)*TR
END as TotalBill
FROM (
SELECT C.firstName||''||C.lastName as CustomerName, R.newReading previousRead,
lead(R.newReading) OVER (PARTITION BY R.meterID ORDER BY R.dateVisited) AS newRead, B.firstconsumptionRate as FR,
B.secondconsumptionRate as SR, B.thirdconsumptionRate as TR
FROM reading R, serviceaddress S, meter W, customer C, rate A, nonresidentialrate B
WHERE W.meterID = S.meterID
AND R.meterID = W.meterID
AND A.rateID = S.rateID
AND B.rateID = A.rateID
AND C.custID = S.custID
AND C.custType = 'Non-residential'
AND r.datevisited >= TO_DATE('01-06-2014','DD-MM-YYYY')
AND r.datevisited < TO_DATE('31-07-2014','DD-MM-YYYY')
)where newRead is not null;
Were it me, I'd probably use a CASE statement and structure the code for clarity rather than trying to eke out every last cycle of performance (unless you're really in an environment where you need every last cycle)
(CASE WHEN newRead-previousRead <= 20
THEN (newRead-previousRead)*0.40
WHEN newRead-previousRead <= 40
THEN 20*0.40 + (newRead-previousRead-20)*0.80
WHEN newRead-previousRead > 40
THEN 20*0.40 + 20*0.80 + (newRead-previousRead-40)*0.90
END)
Now, obviously, there are ways to optimize this (by, for example, computing newRead-previousRead in the inner query once rather than potentially needing to compute it 4 times in the CASE statement). And this is not a particularly flexible option if you want to be able to change the billing structure frequently (in which case the tiers and rates would need to be in a separate table that you read). But it's hopefully a relatively clear expression of the computation.

Need help in the query (oracle 11 g)

First of all, these are my create_table statements.
/*--- Base tables ---*/
CREATE TABLE CUSTOMER (
CUST_ID VARCHAR(10) NOT NULL,
CUST_FNAME VARCHAR(15),
CUST_LNAME VARCHAR(15),
CUST_HP NUMBER(10),
CUST_EMAIL VARCHAR(40),
primary key (CUST_ID)
);
CREATE TABLE STAFF(
STAFF_ID NUMBER(12) NOT NULL,
STAFF_FNAME VARCHAR(15),
STAFF_LNAME VARCHAR(15),
STAFF_DOB Date,
STAFF_AGE NUMBER(2),
STAFF_ADDRESS VARCHAR(70),
STAFF_HP NUMBER(10),
STAFF_SALARY NUMBER(6,2),
primary key (STAFF_ID)
);
CREATE TABLE SUPPLIER(
SUPP_ID VARCHAR(10) NOT NULL,
SUPP_NAME VARCHAR(30),
SUPP_TEL NUMBER(10),
SUPP_EMAIL VARCHAR(25),
SUPP_ADDRESS VARCHAR(80),
SUPP_CITY VARCHAR(20),
SUPP_STATE VARCHAR(10),
SUPP_ZIP NUMBER(5),
primary key (SUPP_ID)
);
CREATE TABLE PRODUCT(
PROD_ID VARCHAR(10) NOT NULL,
PROD_NAME VARCHAR(30),
PROD_DESC VARCHAR(70),
R_UNIT_PRICE NUMBER(3,2) DEFAULT 4.50,
L_UNIT_PRICE NUMBER(3,2) DEFAULT 5.00,
primary key (PROD_ID)
);
CREATE TABLE INGREDIENT(
ING_ID VARCHAR(10) NOT NULL,
ING_NAME VARCHAR(20),
ING_DESC VARCHAR(60),
primary key (ING_ID)
);
CREATE TABLE TOPPING(
TOP_ID VARCHAR(10) NOT NULL,
TOP_NAME VARCHAR(20),
TOP_DESC VARCHAR(40),
TOP_PRICE NUMBER(2,2),
primary key (TOP_ID)
);
/*--- Child tables ---*/
CREATE TABLE ORDERS(
ORDERS_ID VARCHAR(10) NOT NULL,
CUST_ID VARCHAR(10) NOT NULL,
STAFF_ID NUMBER(12) NOT NULL,
TOTAL_PRICE NUMBER(5,2),
ORDERS_DATE DATE,
primary key (ORDERS_ID),
foreign key (CUST_ID) references CUSTOMER(CUST_ID),
foreign key (STAFF_ID) references STAFF(STAFF_ID)
);
CREATE TABLE ORD_DETAIL(
SK1_ID NUMBER(4) NOT NULL,
ORDERS_ID VARCHAR(10) NOT NULL,
PROD_ID VARCHAR(10) NOT NULL,
TOP_ID VARCHAR(10) NOT NULL,
TEATYPE VARCHAR(8),
CUPSIZE CHAR(1),
QTY NUMBER(2),
CONSTRAINT CHK_CUPSIZE CHECK (CUPSIZE = 'R' OR CUPSIZE = 'L'),
CONSTRAINT CHK_TEATYPE CHECK (TEATYPE = 'Oolong' OR TEATYPE = 'Jasmine'),
primary key (SK1_ID),
foreign key (ORDERS_ID) references ORDERS(ORDERS_ID),
foreign key (PROD_ID) references PRODUCT(PROD_ID),
foreign key (TOP_ID) references TOPPING(TOP_ID)
);
CREATE TABLE PROD_ING(
PROD_ID VARCHAR(10) NOT NULL,
ING_ID VARCHAR(10) NOT NULL,
primary key (PROD_ID , ING_ID),
foreign key (PROD_ID) references PRODUCT(PROD_ID),
foreign key (ING_ID) references INGREDIENT(ING_ID)
);
CREATE TABLE ING_SUPP(
ING_ID VARCHAR(10) NOT NULL,
SUPP_ID VARCHAR(10) NOT NULL,
SUPP_PRICE NUMBER(6,2),
primary key (ING_ID, SUPP_ID),
foreign key (ING_ID) references INGREDIENT(ING_ID),
foreign key (SUPP_ID) references SUPPLIER(SUPP_ID)
);
And my query is this:Which employee served the most number of customers?
But when I executed these statements:
SELECT MAX (COUNT (O.CUST_ID)) AS "Served customer"
FROM STAFF S, ORDERS O
WHERE (S.STAFF_ID = O.STAFF_ID)
GROUP BY O.STAFF_ID
HAVING COUNT (O.CUST_ID) > 0;
What I got was there was a column named "Served customer" with the maximum number only.
So, now my question is how to display the employee's ID, first name and last name along with
"Served customer" column.
The question is: "Which employee served the most number of customers? " Your query does not even return information about the employee, only about the number of customers.
The following aggregation returns for each staff member, the number of customers who were served:
SELECT O.STAFF_ID, COUNT(O.CUST_ID) AS "Served customer"
FROM STAFF SS JOIN
ORDERS O
ON S.STAFF_ID = O.STAFF_ID
GROUP BY O.STAFF_ID;
To get the maximum number we just need to order this by the count and take the first row. In Oracle, this uses a subquery:
SELECT so.*
FROM (SELECT O.STAFF_ID, COUNT(O.CUST_ID) AS "Served customer"
FROM STAFF SS JOIN
ORDERS O
ON S.STAFF_ID = O.STAFF_ID
GROUP BY O.STAFF_ID
ORDER BY COUNT(O.CUST_ID) DESC
) so
WHERE rownum = 1;

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.