Counting in Oracle 11g - sql

all day I am struggling with oracle exrcises and again I stuck. I need to select last names of boxers with their wins of each weight category.
So I have:
table "boxer" with columns: id, fname, lname, weight
table "fight" with two foreign keys from table boxer (id_boxer1 and id_boxer2) and with one column winner (if boxer1 won then winner will be number 1, if boxer2 won then winner will be number 2)
table "category_weight" with columns: id, min_weight, max_weight, name (of a category)
Example:
CREATE TABLE category_weight(
id INTEGER NOT NULL,
min_weight SMALLINT NOT NULL,
max_weight SMALLINT NOT NULL,
name VARCHAR2(20) NOT NULL
);
ALTER TABLE category_weight ADD CONSTRAINT category_weight_pk PRIMARY KEY ( id );
CREATE TABLE boxer(
id INTEGER NOT NULL,
fname VARCHAR2(20) NOT NULL,
lname VARCHAR2(20) NOT NULL,
weight INTEGER NOT NULL
);
ALTER TABLE boxer ADD CONSTRAINT boxer_pk PRIMARY KEY ( id );
CREATE TABLE fight(
id INTEGER NOT NULL,
winner SMALLINT NOT NULL,
id_category_weight INTEGER NOT NULL,
id_boxer1 INTEGER NOT NULL,
id_boxer2 INTEGER NOT NULL
);
ALTER TABLE fight ADD CONSTRAINT fight_pk PRIMARY KEY ( id );
ALTER TABLE fight
ADD CONSTRAINT boxer_fk FOREIGN KEY ( id_boxer1 )
REFERENCES boxer ( id );
ALTER TABLE fight
ADD CONSTRAINT boxer_fk2 FOREIGN KEY ( id_boxer2 )
REFERENCES boxer ( id );
ALTER TABLE fight
ADD CONSTRAINT categ_weight_fk FOREIGN KEY ( id_category_weight )
REFERENCES category_weight ( id );
INSERT INTO boxer
VALUES ('1', 'Johnny','Johnny','60');
INSERT INTO boxer
VALUES ('2', 'Anthonny','Anthonny','54');
INSERT INTO boxer
VALUES ('3', 'Anonimm','Anonimm','59');
INSERT INTO boxer
VALUES ('4', 'John','Johnowski','71');
INSERT INTO category_weight
VALUES ('1', '1','70','category1');
INSERT INTO category_weight
VALUES ('2', '71','100','category2');
INSERT INTO fight
VALUES ('1','1','1','1','2');
INSERT INTO fight
VALUES ('2','2','1','3','1');
Boxer with ID "1" won two fights in category1, so the result should be:
Lname Category Wins
Johnny category1 2

Here, try this:
SELECT b.lname,
cw.max_weight AS WEIGHT_CLASS,
COUNT(CASE WHEN f.winner = b.id THEN 1 ELSE NULL END) AS WINS
FROM boxer b
INNER JOIN fight f ON b.id = f.id_boxer1 OR b.id = f.id_boxer2
INNER JOIN category_weight cw ON f.id_category_weight = cw.id
GROUP BY b.lname, cw.max_weight

Related

Getting duplicate data when using the select statements

I'm getting duplicate data when trying to use the select statements, I have 9 rooms but I'm getting around 50-70 rooms when trying to display them. Help please?
I'm trying to insert data and display it using the select statement.
create table gym (
GymName VARCHAR(200) primary key,
openTime time not null,
closeTime time not null,
Price decimal not null,
);
create table Spa (
spaName VARCHAR(200) primary key,
openTime time not null,
closeTime time not null,
Price decimal not null,
);
create table customer (
CustomerID int primary key,
Firstname varchar(200) not null,
LastName varchar(200) not null,
DOB date not null check (DATEDIFF(year,DOB,getdate ()) > 18) ,
Gender char(4) not null check(Gender ='M' or Gender = 'F'),
Address varchar(200) not null default 'Jordan',
spaName VARCHAR(200) foreign key references Spa(spaName),
GymName VARCHAR(200) foreign key references gym(GymName),
);
Create table CustomerPhoNo (
CustomerID int foreign key references customer(CustomerID),
PhoneNo bigint not null,
);
create table Room (
roomNo int primary key,
Availability char(4) not null,
NoOfBeds int not null,
Rate int not null,
CheckIn date,
CheckOut date,
Price Decimal not null,
Breakfast char(4),
CustomerID int foreign key references customer(CustomerID),
);
create table LocationOfRoom (
roomNo int foreign key references Room(roomNo),
seaview char(4),
Location varchar(20) not null,
);
create table RoomType (
roomNo int foreign key references Room(roomNo),
familyRoom char(4),
doubleRoom char(4),
singleRoom char(4),
);
create table Gservice (
GymName VARCHAR(200) foreign key references gym(GymName),
Service VARCHAR(500) not null,
MachineType VARCHAR(500) not null,
);
create table PaymentCard (
CardID int primary key,
issueDate date not null,
Expirydate date not null,
CustomerID int foreign key references customer(CustomerID),
);
insert into customer values (325,'Mohammad','Alasharan','06-04-1984','M','Amman', 'BeautySpa', 'StrongBody')
insert into customer values (348,'John','Shelby','10-18-1998','M','Birmingham', 'LushLife', 'SilverGym')
insert into customer values (495,'Thomas','Hoffman','04-26-1968','M','Johannesburg', 'RelaxationTherapy', 'SilverGym')
insert into customer values (194,'Anne','Frank','07-22-2001','F','Frankfurt', 'BeautySpa', 'StrongBody')
insert into customer values (628,'Katie','Swan','02-10-1997','F','New South Wales', 'LushLife', 'FitnessHeroes')
insert into customer values (246,'Mahmoud','Alkutaifan','04-21-1994','M','Amman', 'BeautySpa', 'FitnessHeroes')
insert into customer values (864,'Karl-Heinz','Rummenigge','09-25-1955','M','Lippstadt', 'RelaxationTherapy', 'FitnessHeroes')
insert into customer values (824,'Dennis','Law','09-21-1979','M','london', 'RelaxationTherapy', 'FitnessHeroes')
insert into customer values (463,'Carles','Puyol','06-17-1973','M','madrid', 'LushLife', 'FitnessHeroes')
insert into Room values (124,'yes','1','4',null,null,'30','yes',null)
insert into Room values (135,'no','2','5','05-06-2022','05-09-2022','55','yes',495)
insert into Room values (121,'yes','1','3',null,null,'40','yes',null)
insert into Room values (139,'no','3','4','05-10-2022','05-14-2022','110','no',194)
insert into Room values (131,'no','3','3','05-18-2022','05-22-2022','130','yes',348)
insert into Room values (136,'no','4','4','04-14-2022','04-24-2022','120','yes',194)
insert into Room values (179,'yes','4','5',null,null,'95','no',null)
insert into Room values (138,'no','3','3','04-02-2022','04-06-2022','75','no',246)
insert into Room values (146,'no','3','5','05-10-2022','05-14-2022','80','yes',864)
insert into LocationOfRoom values (124,'no','south')
insert into LocationOfRoom values (135,'yes','north')
insert into LocationOfRoom values (121,'yes','south')
insert into LocationOfRoom values (139,'no','north')
insert into LocationOfRoom values (131,'no','East')
insert into LocationOfRoom values (136,'yes','west')
insert into LocationOfRoom values (179,'no','south')
insert into LocationOfRoom values (138,'no','west')
insert into LocationOfRoom values (146,'yes','north')
insert into RoomType values (124,'no','no','yes')
insert into RoomType values (135,'no','yes','no')
insert into RoomType values (121,'yes','no','no')
insert into RoomType values (139,'no','no','yes')
insert into RoomType values (131,'no','no','yes')
insert into RoomType values (136,'no','no','yes')
insert into RoomType values (179,'no','no','yes')
insert into RoomType values (138,'no','yes','no')
insert into RoomType values (146,'no','no','yes')
-- display Total number of customers who booked a single room with sea view option
select count(Firstname)
from LocationOfRoom, customer, RoomType, Room
where seaview='yes' and singleRoom='yes'
Any help would be greatly appreciated, thank you in advance!
Your FROM clause is missing the join condition for each table. In other words you are getting the cartesian product (every combination of rows) of the tables. Even distinct won't help (it will get the wrong answer). Use join conditions to link the keys of each table to each other. I'll leave this an exercise for you to try out, but this should be enough information to help you out.
I believe the solution for your problem is that you need to use DISTINCT:
SELECT COUNT(DISTINCT(Firstname))
FROM LocationOfRoom, customer, RoomType, Room
WHERE seaview='yes' AND singleRoom='yes'
I have tested it and it retrieves 9 Rooms.

SQL: "foreign key constraint fails" error message

I get an error when attempting to insert data into the songs table. I'm not sure why.
Any help would be greatly appreciated. Thanks. This is me adding details so it will let me post haha.
create table artist
(
id int primary key auto_increment,
name varchar(128) not null,
nationality varchar(128)
) ENGINE=InnoDB;
insert into artist (name, nationality) values ('Metallica', 'American');
insert into artist (name, nationality) values ('Rush', 'Canadian');
create table album
(
id int primary key auto_increment,
name varchar (128) not null,
artist int not null,
foreign key (artist) references artist(id),
genre int,
foreign key (genre) references genre(id)
) ENGINE=InnoDB;
insert into album (name, artist, genre) values ('Ride the Lightning', 1, 1);
insert into album (name, artist, genre) values ('Moving Pictures', 2, 2);
create table song
(
id int primary key auto_increment,
name varchar (128) not null,
duration varchar (128),
album int not null,
foreign key (album) references album(id)
) ENGINE=InnoDB;
insert into song (name, duration, album) values ('Fade to Black', '1 min', 1);
insert into song (name, duration, album) values ('Tom Sawyer', '2 min', 2);
create table genre
(
id int primary key auto_increment,
name varchar (128) not null,
description varchar (256)
) ENGINE=InnoDB;
insert into genre (name, description) values ('Rock', 'Lots of drums and guitars');
insert into genre (name, description) values ('Metal', 'Drums and guitars on steroids');
The order of your code is causing the problem. You need to move the
create table genre
(
id int primary key auto_increment,
name varchar (128) not null,
description varchar (256)
) ENGINE=InnoDB;
insert into genre (name, description) values ('Rock', 'Lots of drums and guitars');
insert into genre (name, description) values ('Metal', 'Drums and guitars on steroids');
Up above the "Create table album"
Here is the correct way to do it: HOW TO DO IT
This is some reasons why it did not work:
There is no table "genre" when you try to create table album:
create table album
(
id int primary key auto_increment,
name varchar (128) not null,
artist int not null,
foreign key (artist) references artist(id),
genre int,
foreign key (genre) references genre(id)
) ENGINE=InnoDB;
Here is the DEMO
Also, when you create table "genre" on time, there is another problem. You have to insert data in table "genre" to be able to insert other data.
Here is the DEMO where all works.
One is the order of the create and insert statements shouldve given you error already as table referres doesnt exists etc.
Assuming if the order is rightly implemented, as per the above error not able to insert data in songs is likely because
Your album table has a null id or id which you are inserting in songs doesnt exists in album first insert the data in album table then insert into songs table as the foreign key of songs table is checking the album table for id data

Locking Order of table with foreign key constraint?

If I create a schema such as the following:
create table org
(
org_id bigint not null auto_increment,
name varchar(255) not null,
primary key(org_id)
);
create table user
(
user_id bigint not null auto_increment,
name varchar(255) not null,
org_id bigint not null,
primary key(user_id),
foreign key(org_id) references org (org_id)
);
Where the org table has one entry:
insert into org (name) values ('org 1');
If I run the following sql statement:
insert into user (name, org_id) values ('user 1', 1);
In what order will the tables be locked? Is it deterministic? What if there were a second foreign key constraint to another table?

Not expected result of the query

There is a query:
select * from
(
select
p.ID
from
MY_PRODUCT_PARENT_LINK pLink
inner join MY_PRODUCT p on pLink.FK_PARENT=p.ID
order by
pLink.DESCENDANT_LVL desc
)
where rownum <= 1
;
The inner query returns one row with not null value of p.ID.
The outer query - one row with null value of p.ID. Here expected not null value.
The database sever is Oracle 11g.
There is a code to reproduction:
CREATE TABLE MY_PRODUCT
(
FK_PARENT NUMBER(19),
ID NUMBER(19) NOT NULL,
NAME VARCHAR2(4000 BYTE),
CONSTRAINT PK_MY_PRODUCT PRIMARY KEY (ID)
);
INSERT INTO MY_PRODUCT (FK_PARENT, ID,NAME) VALUES (null, 111111,'PRODUCT_NAME_01');
INSERT INTO MY_PRODUCT (FK_PARENT, ID,NAME) VALUES (null, 111112,'PRODUCT_NAME_02');
CREATE TABLE MY_PRODUCT_PARENT_LINK
(
ID NUMBER(19) NOT NULL,
FK_PRODUCT NUMBER(19) NOT NULL,
FK_PARENT NUMBER(19) NOT NULL,
DESCENDANT_LVL NUMBER(19) NOT NULL,
primary key (ID)
);
ALTER TABLE MY_PRODUCT_PARENT_LINK ADD
CONSTRAINT MY_PRD_PARENT_TO_MY_PRODUCT
FOREIGN KEY (FK_PRODUCT)
REFERENCES MY_PRODUCT (ID) ON DELETE CASCADE;
ALTER TABLE MY_PRODUCT_PARENT_LINK ADD
CONSTRAINT MY_PRD_PARENT_TO_PARENT
FOREIGN KEY (FK_PARENT)
REFERENCES MY_PRODUCT (ID) ON DELETE CASCADE;
INSERT INTO MY_PRODUCT_PARENT_LINK (ID, FK_PRODUCT, FK_PARENT, DESCENDANT_LVL) VALUES (211111, 111112, 111111, 1);
Try and select the ID in the outer query and see if that returns the result. so instead of select * in the outer do select ID.

Movie booking: How to let every show have its own set of seats?

I have made a movie booking database in mysql workbench (6.2). This database is then connected to eclipse where I in java have programmed a GUI for the movie booking system.
Everything works well with the GUI/database but there is one logical problem:
If a reservation is made for a show, naturally, the number of seats left in that theater where that show is to be played, will be reduced by 1 for every reservation. But if there is a show that's on a different date but on the same theater then this theaters seats is also reduced by 1 which is wrong.
E.g. a show on Monday should have its own set of seats and one on Tuesday should have its own. A solution could be to create a new column 'nbrseats' in 'shows' but I want it to get its seats from Theaters if that's possible.
Database
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
Thanks!
Just make a new column to store the number of booked seats in the reservations table. Then you can write a query to calculate the number of free seats based on the reservations made and the seats available in this theater.
Example to get free seats of showid 1, with two reservations of 5 and 2 seats:
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
seats int not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
insert into reservations values
(null,'Temp1', 1, 5),
(null,'Temp1', 1, 2),
(null,'Temp1', 2, 3);
select
Shows.id,
Shows.theatername,
Theaters.NbrSeats,
sum(reservations.seats),
Theaters.NbrSeats-sum(reservations.seats) freeseats
from Shows
left join Theaters
on Shows.theatername = Theaters.theatername
left join reservations
on Shows.id = reservations.showId
where Shows.id = 1
group by
Shows.id,
Shows.theatername,
Theaters.NbrSeats
Database is correct, it was a matter of querying
here is an (somewhat primitive) example query for id = 2:
select nbrseats - (select count(showId) from reservations
where showId = (select id from shows where id = 2)) from theaters
where theatername = (select theatername from shows where id = 2);