Joining multiple tables + HAVING clause - sql

I have 4 tables :
create table Hotel (
numHotel int primary key,
nomHotel varchar(30),
ville varchar(30),
etoiles tinyint
);
create table Chambre (
numChambre int identity primary key,
numHotel int foreign key references Hotel(numHotel),
etage tinyint,
prixnuit smallmoney not null check (prixnuit>=100)
);
create table Client (
cinClient varchar(10) primary key,
nom varchar(30),
prenom varchar(30),
adresse varchar(255) default 'non renseignée',
telephone varchar(10) check (telephone like '0%' and len(telephone)=10)
);
create table reservation (
numReservation int identity primary key,
numChambre int foreign key references Chambre(numChambre),
numCl varchar(10) foreign key references Client(cinClient),
dateArrivee date,
dateDepart date,
constraint ck_dates check ((Datediff(day,dateArrivee,dateDepart)>0))
);
Column names are French, but I think they're understandable.
So the question is : I need to select the names of Hotels (nomHotel) having achieved a total price higher than a certain price (e.g. 10000)
This is what I did on paper :
select nomHotel from Hotel h join Chambre ch on h.numHotel=ch.numChambre join reservation r on ch.numChambre=r.numChambre
group by nomHotel
having COUNT(r.numChambre)*ch.prixnuit>10000
And (of course) I got it wrong.
Any Help is appreciated, Thanks.
translations : "prixnuit" is the room's (chambre) price per night.

The total revenue (I think) is based on the number of reservations.
I'm thinking you need to calculate the number of nights per reservation, no?
So, maybe:
select nomHotel,
sum(Datediff(day,r.dateArrivee,r.dateDepart)*ch.prixnuit)
from Hotel h join Chambre ch on h.numHotel=ch.numChambre join reservation r
on ch.numChambre=r.numChambre
group by nomHotel
having sum(Datediff(day,r.dateArrivee,r.dateDepart)*ch.prixnuit)>10000

select nomHotel, sum(Datediff(day,dateArrivee,dateDepart) * prixnuit)
from Hotel h join Chambre ch on h.numHotel=ch.numHotel
join reservation r on ch.numChambre=r.numChambre
group by nomHotel
having sum(Datediff(day,dateArrivee,dateDepart) * prixnuit)>1000

Related

How to find the champion with the highest number of selections in match in SQLlite

I'm trying to do this query : find the champion with the highest number of selections in match for each champion found display their name as well as the number of times they ha\ve been selected in match .
Here are the tables:
CREATE TABLE champions
(
id_champion INT PRIMARY KEY NOT NULL,
name VARCHAR(20),
title VARCHAR(20),
attack INT,
defense INT,
magic INT,
difficulty INT
);
CREATE TABLE players
(
id_player INT PRIMARY KEY NOT NULL,
name VARCHAR(20),
country VARCHAR(20)
);
CREATE TABLE matchs
(
id_match INT,
player INT,
champion INT,
number INT,
gold INT,
team INT,
position VARCHAR(10),
PRIMARY KEY (id_match, player),
FOREIGN KEY(id_match) REFERENCES matchsmeta(id_match) ON DELETE SET NULL,
FOREIGN KEY(player) REFERENCES players(id_player) ON DELETE SET NULL,
FOREIGN KEY(champion) REFERENCES champions(id_champion) ON DELETE SET NULL
);
CREATE TABLE matchsmeta
(
id_match INT PRIMARY KEY NOT NULL,
time INT,
victory INT,
date DATE,
game_mode VARCHAR(10)
);
First aggregate in the table matchs to get the number of times each champion was picked and use MAX() window function to get the max of these counts:
SELECT champion,
COUNT(*) counter,
MAX(COUNT(*)) OVER () max_counter
FROM matchs
GROUP BY champion
Then join the above query to the table champions:
SELECT c.name, m.counter
FROM champions c
INNER JOIN (
SELECT champion,
COUNT(*) counter,
MAX(COUNT(*)) OVER () max_counter
FROM matchs
GROUP BY champion
) m ON m.champion = c.id_champion
WHERE m.counter = m.max_counter;
You have to make the count of times a champion appears in matchs table.
Then you can join the champions table to get the name.
SELECT
m.champion,
c.name,
SUM(1) as num_times_picked
FROM matchs m
LEFT JOIN champions c on (m.champion = c.id_champion)
GROUP BY m.champion
ORDER BY 3 DESC

How do i fill my table with data from 3 different tables?

So I am working on a football world cup database. These are my important tables:
CREATE TABLE Countries(
Cid SERIAL PRIMARY KEY,
Name VARCHAR(256) NOT NULL UNIQUE
);
CREATE TABLE Stadiums(
Sid SERIAL PRIMARY KEY,
Name VARCHAR(256) NOT NULL UNIQUE,
Cid INT REFERENCES Countries NOT NULL
);
CREATE TABLE Groups(
Gid SERIAL PRIMARY KEY,
Name VARCHAR(64) NOT NULL,
TYear SMALLINT REFERENCES Tournaments NOT NULL
);
CREATE TABLE Teams(
Tid SERIAL PRIMARY KEY,
Cid INT REFERENCES Countries NOT NULL,
Gid INT REFERENCES Groups NOT NULL
);
CREATE TABLE Matches(
Mid INT PRIMARY KEY,
HomeTid INT REFERENCES Teams NOT NULL,
VisitTid INT REFERENCES Teams NOT NULL,
HomeScore SMALLINT NOT NULL,
VisitScore SMALLINT NOT NULL,
MatchDate DATE NOT NULL,
MatchType VARCHAR(64) NOT NULL,
Sid INT REFERENCES Stadiums NOT NULL
);
CREATE TABLE tempmatches(
year INTEGER,
host_country VARCHAR(255),
match_id INTEGER,
type VARCHAR(255),
date DATE,
location1 VARCHAR(255),
team1 VARCHAR(255),
team2 VARCHAR(255),
score1 INTEGER,
score2 INTEGER
);
so my current problem is that I need to populate the columns HomeTid and VisitId of the Matches table with the tid's from the team's table that corresponds with the country of that team from the countries table but I'm not sure how to do that. I tried a few queries but none of them seemed to work. Has anyone an idea on how to solve this?
Using JOIN keyword you can combine 2 tables data.
Here, in this case, you have to use 3-way join.
Eg:
3-way JOIN can be used in this way:
SELECT * FROM table1 JOIN table2 ON table1.col1=table2.col2 JOIN table3 ON table3.col3=table.col1;
Here the 2 tables will get joined based on the columns mentioned after the "ON" keyword.
Here is a reference link in which JOIN is explained clearly
https://www.w3schools.com/sql/sql_join.asp
Use JOIN operation. In SQL it helps to combine several tables(queries) in one

SQL Query that displays the number of athletes that have competed in at least ten different places(locations)

I'm building a query based on the fact that they have competed in ten or more places. Note that it does not matter how many sports or competitions they competed in, just how many places they have competed in.
CREATE TABLE Gender (
gender CHAR(1),
description VARCHAR(10),
PRIMARY KEY (gender));
CREATE TABLE People (
ID INT,
name VARCHAR(50),
gender CHAR(1),
height FLOAT,
PRIMARY KEY (ID),
FOREIGN KEY (gender) REFERENCES Gender (gender));
CREATE TABLE Sports (
ID INT,
name VARCHAR(50),
record FLOAT,
PRIMARY KEY (ID),
UNIQUE (name));
CREATE TABLE Competitions (
ID INT,
place VARCHAR(50),
held DATE,
PRIMARY KEY (ID));
CREATE TABLE Results (
peopleID INT NOT NULL,
competitionID INT NOT NULL,
sportID INT NOT NULL,
result FLOAT,
PRIMARY KEY (peopleID, competitionID, sportID),
FOREIGN KEY (peopleID) REFERENCES People (ID),
FOREIGN KEY (competitionID) REFERENCES Competitions (ID),
FOREIGN KEY (sportID) REFERENCES Sports (ID));
If anyone can help me with this it would be much appreciated!
As commented by Brad, you can use a simple aggregated query that JOINs table People with Results, with a HAVING BY clause to filter on the number of competitions each person participated to. It seems like you don’t need to bring in any other table to achieve your goal.
SELECT
p.ID,
p.Name
FROM
People p
Results r ON r.peopleID = p.ID
GROUP BY
p.ID,
p.Name
HAVING COUNT(*) >= 10

SQL double primary key, many-to-many relationship

I'd like to connect 3 tables. In one of them I must use a compound primary key. I know, how to deal with single. I have the following tables to connect:
CREATE TABLE Med_list
(
ID_med_list INT IDENTITY(200001,1) ,
No_med_list INT,
ID_med INT REFERENCES Med(ID_med),
PRIMARY KEY(ID_med_list, No_med_list)
)
CREATE TABLE Med
(
ID_med INT IDENTITY(3001,1) PRIMARY KEY ,
Name VARCHAR(20)
)
CREATE TABLE Visit
(
ID_Visit INT IDENTITY(600001,1) PRIMARY KEY,
ID_patient INT REFERENCES Patients(ID_patient),
Visit_date Datetime,
ID_med_duty INT,
No_med_list INT
)
I would like to every patient could have more than one medicine during one visit. I don't know how to connect table Visit and Med_list the way acceptable to SQL Server.
Thank you in advance for every hint or help:)
You need a many to many relation, if Med_list is supposed to be this relation (medicine to visits) then you are only missing one foreign key that points to the visit so the tables relation looks like this
Patient. <--- Visit. <--- Med_list. ---> Meds
The tables like this:
CREATE TABLE Med_list
(
ID_med_list INT IDENTITY(200001,1) ,
No_med_list INT,
ID_med INT REFERENCES Med(ID_med),
ID_Visit INT REFERENCES Visit(ID_Visit)
PRIMARY KEY(ID_med_list, No_med_list)
)
CREATE TABLE Med
(
ID_med INT IDENTITY(3001,1) PRIMARY KEY ,
Name VARCHAR(20)
)
CREATE TABLE Visit
(
ID_Visit INT IDENTITY(600001,1) PRIMARY KEY,
ID_patient INT REFERENCES Patients(ID_patient),
Visit_date Datetime,
ID_med_duty INT,
No_med_list INT
)
And your query can look like this
Select * From patients p
Join Visit v on v.ID_Patient = p.ID_Patient
Join Med_list ml on ml.ID_Visit = v.ID_Visit
Join Med m on m.ID_med = ml.ID_med
You could try this
I am also new in many-to-many relationship query.
SQLFiddle Example
SELECT
P.name,
M.Name
FROM
med_list ML
LEFT JOIN med M ON m.ID_med=ML.ID_med
LEFT JOIN visit V ON V.ID_Visit=ML.ID_Visit
LEFT JOIN patients P ON P.ID_patient=V.ID_patient

sql query details for a certain date

I have the following database:
create table Hotel (
HNo char(4),
Name varchar(20) not null,
Address varchar(50),
Constraint PK_Hotel Primary Key (HNo))
)
create table Room (
RNo char(4),
HNo char(4),
Type char(6) not null,
Price decimal (7,2),
Constraint PK_Room Primary Key (HNo, RNo),
Constraint FK_Room Foreign Key (HNo)
references Hotel (HNo)
)
create table Guest (
GNo char(4),
Name varchar(20) not null,
Address varchar(50),
Constraint PK_Guest Primary Key (GNo)
)
create table Booking (
HNo char(4),
GNo char(4),
DateFrom date,
DateTo date,
RNo char(4),
Constraint PK_Booking Primary Key (HNo, GNo, DateFrom),
Constraint FK_Booking Foreign Key (GNo)
references Guest (GNo),
Constraint FK_Booking_room Foreign Key (HNo, RNo)
references Room (HNo, RNo),
Constraint FK_Booking_hotel Foreign Key (HNo)
references Hotel (HNo)
)
What I am struggling with is using the dateto=> <=datefrom and getting it to work.
For the 26th march 1997, I need to list the details of all rooms in all hotels, including the name of any guests who were staying in the room. I'm not too bad with joining the tables etc, but am not sure how to do it as a whole on the specified date? Any ideas?
SELECT
h.Name,
h.Address,
r.RNo,
r.HNo,
r.Type,
r.Price,
G.Name,
G.Address,
...
FROM Hotel AS h
INNER JOIN Room AS r ON h.HNo = r.HNo
INNER JOIN Guest AS g ON r.RNo = g.RNo
INNER JOIN Booking AS b ON b.GNo = g.GNo
AND b.HNo = h.HNo
WHERE b.DateFrom <= #DateFrom
AND b.DateTo => #DateTo;
SELECT b.datefrom, b.dateto, h.name AS hotelname
, b.rno
, r.type
, g.name AS guestname
FROM booking b
JOIN hotel h ON b.hno = h.hno
JOIN guest g ON g.gno = b.gno
JOIN room r ON b.rno = r.rno
WHERE #yourDate BETWEEN b.datefrom AND b.dateto
EDIT :
Replace the #yourDate in the last line with a suitable expression supported by your DBMS.
E.g., in Oracle, there is a function TO_DATE which converts a given string to date, like TO_DATE('26-MAR-1997') BETWEEN b.datefrom AND b.dateto. In SQL Server there is CAST function.