sql query details for a certain date - sql

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.

Related

Get Max record from query SQL Server

I have the following tables
CREATE TABLE Staff
(
staffID int,
fullName varchar(100) NOT NULL,
s_category varchar(25),
s_email varchar(50),
s_contactNo int,
speciality varchar(100),
qualifications varchar(250),
pre_employment varchar(200),
salary numeric(8,2),
staff_gender char(1),
staff_joined_date datetime,
branch_allocated int,
CONSTRAINT PK_Staff
PRIMARY KEY (staffID),
CONSTRAINT FK_Staff_Branch
FOREIGN KEY (branch_allocated) REFERENCES Branch(branchID)
ON DELETE CASCADE,
CONSTRAINT CHK_StaffGender CHECK (staff_gender='M' OR staff_gender='F'),
CONSTRAINT CHK_FullName CHECK (fullName NOT LIKE '%[^A-Za-z ]%'),
CONSTRAINT CHK_SALARY CHECK (salary>0 AND salary<=150000)
);
CREATE TABLE Appointment
(
appID int,
patientId int,
staffId int,
appDateTime DateTime,
CONSTRAINT PK_Appointment PRIMARY KEY (appID),
CONSTRAINT FK_Appointment_Patient
FOREIGN KEY (patientId) REFERENCES Patient(patientID)
ON DELETE CASCADE,
CONSTRAINT FK_Appointment_Staff
FOREIGN KEY (staffId) REFERENCES Staff(staffID)
ON DELETE CASCADE,
CONSTRAINT CHK_AppointmentDate CHECK (appDateTime>=GETDATE())
);
I want to get the doctor(s) with maximum number of patients.
I have created the query as follows.
SELECT
s.staffID AS 'ID',s.fullName AS 'Name', COUNT(a.appID) AS 'Number of Patients'
FROM
Staff s
INNER JOIN
Appointment a ON s.staffID = a.staffId
GROUP BY
s.staffID, s.fullName
ORDER BY
'Number of Patients' DESC
But this returns all doctors. Can you help me to find the doctor with the largest number of patients?
WITH cte AS (
SELECT
s.staffID AS ID,
s.fullName AS Name,
COUNT(a.appID) AS [Number of Patients],
DENSE_RANK() OVER (ORDER BY COUNT(a.appID) DESC) AS rank
FROM Staff s
LEFT JOIN Appointment a
ON s.staffID = a.staffId
GROUP BY s.staffID, s.fullName
)
SELECT
ID, Name, [Number of Patients]
FROM cte
WHERE rank = 1;
Can you try this
SELECT TOP number|percent column_name(s)
FROM table_name
WHERE condition;
on your situation SELECT TOP 1

Problems with a query PostgreSQL

I have some problems with a Query that I can not get out, the structure of the tables is as follows:
child
CREATE TABLE CHILD(
child_id SMALLINT,
child_name VARCHAR(255) NOT NULL,
birth_date DATE NOT NULL,
gender VARCHAR(255) NOT NULL,
address VARCHAR(255),
city VARCHAR(255),
CONSTRAINT PK_CHILD PRIMARY KEY(child_id)
letter
CREATE TABLE LETTER(
letter_id SMALLINT,
arrival_date DATE NOT NULL,
number_toys INTEGER NOT NULL,
delivery_mode VARCHAR(255) NOT NULL,
child_id SMALLINT,
CONSTRAINT PK_LETTER PRIMARY KEY(letter_id),
CONSTRAINT CHILD_FK FOREIGN KEY (child_id) REFERENCES CHILD(child_id)
);
wished_toy
CREATE TABLE WISHED_TOY(
letter_id SMALLINT,
toy_id SMALLINT,
CONSTRAINT PK_WISHED_TOY PRIMARY KEY(letter_id, toy_id),
CONSTRAINT LETTER_FK FOREIGN KEY (letter_id) REFERENCES LETTER(letter_id)
CONSTRAINT LETTER_FK FOREIGN KEY (toy_id) REFERENCES TOY(toy_id)
);
toy
CREATE TABLE TOY(
toy_id SMALLINT,
toy_name VARCHAR (255) NOT NULL,
price DECIMAL NOT NULL,
toy_type VARCHAR(255) NOT NULL,
manufacturer VARCHAR(255) NOT NULL,
CONSTRAINT PK_TOY PRIMARY KEY(toy_id),
);
I have to design a query that allows to obtain for each girl born before 2010 the
total number of toys you have ordered. The result must also include
those girls who have not written any letters. Specifically we want the
identifier of the girl, her name and city and the total number of toys ordered
(such as Total_number).
in the gender column of the child table can only be "m" of masculine or "f" of feminine
Do I have to use join?
the part that I have is this
select c.child_id,c.child_name,c.city
from letter l
join child c
on c.child_id=l.child_id
where c.gender='m' and c.birth_date between <='2010/01/01';
select c.child_id,c.child_name,c.city, coalesce( number_toys,0) counted
from
Child c
left outer join letter l
on c.child_id=l.child_id
where c.gender='m' and c.birth_date between <='2010/01/01';
Or
select c.child_id,c.child_name,c.city, count(wt.letter_id) actualToys
from
Child c
left outer join letter l
on c.child_id=l.child_id
left outer join wished_toy wt on l.letter_id=wt.letter_id
where c.gender='m' and c.birth_date between <='2010/01/01'
Group by
c.child_id,c.child_name,c.city
To count the toys referenced by database rows rather than the pre defined count

Joining multiple tables + HAVING clause

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

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

Hotel Reservation System SQL query not returning output for date range for availability of room

CREATE PROCEDURE AVAILABILITY
AS
DECLARE #check_in AS DATETIME
DECLARE #check_out AS DATETIME
SELECT room_id,room_type
FROM room
WHERE room_id NOT IN
(
SELECT room_id
FROM reservation B
JOIN RoomReservation RB
ON B.r_id = RB.r_id
WHERE (check_in <= #check_in AND check_out >= #check_in)
)
GO
Exec AVAILABILITY
create table room(
room_id varchar(5) not null,
room_price varchar(7) not null,
room_type varchar(10) NOT NULL CHECK (room_type IN('Single', 'Deluxe', 'Superior')),
occupied BIT DEFAULT 0 not null,
constraint Room_PK primary key(room_id)
)
create table reservation(
c_id varchar(5) ,
--room_id varchar(5) ,
r_id varchar(5) not null,
e_id varchar(5),
check_in date not null,
check_out date null,
constraint R_PK primary key(r_id),
constraint R_FK foreign key(c_id) references customer,
constraint R_FK1 foreign key(e_id) references employ,
--constraint RM_FK foreign key(room_id) references room
)
create table RoomReservation(
room_id varchar(5),
r_id varchar(5),
constraint RR_FK foreign key(room_id) references room,
constraint RoomR_FK1 foreign key(r_id) references reservation
)
insert into RoomReservation(r_id,room_id)
values --('T1','A1'),
-- ('T2','A2'),
-- ('T3','A3'),
-- ('T4','A4'),
-- ('T5','A3'),
-- ('T6','B11'),
-- ('T7','B12'),
-- ('T8','A4'),
-- ('T9','A5'),
-- ('T10','A1'),
-- ('T11','A7'),
-- ('T12','C25')
insert into customer(c_id,phone,name,CNIC,m_id)
values--('C01','0418814342','saad','3330195894431','M01'),
--('C02','0418814212','shahbaz','3330195894432','M02'),
--('C03','0418814111','feroz','3330195894433',Null),
--('C04','0418814222','serene','3330195894434','M03'),
('C05','0418814333','zoe','3330195894435',Null),
-- ('C06','0418814444','aslam','3330195894436',Null),
-- ('C07','0418814555','saleem','3330195894437','M04'),
-- ('C08','0418814666','zia','3330195894438',Null),
-- ('C09','0418814777','sami','3330195894439',Null),
--('C10','0418814888','usman','3330195894430',Null)
select * from customer
insert into room(room_id,room_price,room_type,occupied)
values('A1','2000','deluxe',1),
('A2','2000','deluxe',1),
('A3','4000','superior',0),
('A4','5000','single',0),
('A5','2000','deluxe',1),
('A6','2000','deluxe',1),
('A7','4000','superior',0),
('A8','5000','single',0),
('A9','2000','deluxe',1),
('A10','4000','superior',0),
('B11','5000','single',0),
('B12','5000','single',0),
('B13','2000','deluxe',1),
('B14','4000','superior',0),
('B15','5000','single',0),
('B16','5000','single',0),
('B17','5000','single',0),
('B18','2000','deluxe',1),
('B19','2000','deluxe',1),
('B20','4000','superior',0),
('C21','4000','superior',0),
('C22','5000','single',0),
('C23','2000','deluxe',1),
('C24','4000','superior',0),
('C25','2000','deluxe',1)
select * from room
insert into reservation(c_id,r_id,e_id,check_in,check_out)
values--('C01','T1','E0001','1-17-2015','1-18-2015'),
--('C01','T3','E0001','2-2-2015','2-6-2015'),
--('C02','T4','E0001','3-12-2015','3-15-2015'),
('C03','T5','E0002','3-12-2015','3-15-2015'),
('C03','T6','E0001','3-15-2015','3-17-2015'),
('C05','T7','E0003','3-17-2015','3-18-2015'),
('C06','T8','E0001','3-17-2015',Null),
('C07','T9','E0003','3-19-2015','3-20-2015'),
('C08','T10','E0001','4-12-2015','4-13-2015'),
('C09','T11','E0003','4-13-2015','4-14-2015'),
('C10','T12','E0001','4-14-2015','4-20-2015')
Instead it returns all the list of rooms in the hotel, not the available rooms within a specified date. I have tried several times to write a procedure or trigger to update occupied column of the room from 0 to 1, 1 to 0, but all my attempts failed.
EDIT:
Ok above has been resolved.
I have three entities,ROOM,ROOMRESERVATION,RESERVATION.
how to update status of the of occupied to 1 once a room has been reserved and to 0 once it no longer is reserved.
There are some mistakes in your query
I hope you have to get check_in date and check_out as parameters
so query should be like beolow
CREATE PROCEDURE AVAILABILITY
#check_in AS DATETIME,
#check_out AS DATETIME
AS
SELECT room_id,room_type
FROM room
WHERE room_id NOT IN
(
SELECT room_id
FROM reservation B
inner JOIN RoomReservation RB
ON B.r_id = RB.r_id
WHERE (check_in <= #check_in AND check_out >= #check_in)
)
GO
and you can call the procedure like
exec AVAILABILITY '1-17-2015','1-18-2015'
This is probably what you want:
SELECT room_id,room_type
FROM room
WHERE room_id NOT IN
(
SELECT room_id
FROM reservation B
JOIN RoomReservation RB
ON B.r_id = RB.r_id
WHERE (check_out >= #check_in AND check_in <= #check_out)
)
At least that's how I did it when I wrote a booking engine years ago.