Relational algebra one to many, division - sql

I have seen many examples of division but none helped me understand how to solve the following problem:
Relations are:
Patient (Pid, Did, Pname, Disease, Severity)
Doctor (Did, Cname, Dname, Specialty)
Clinic (Cname, Mname, Type, City)
Question is: Find all pairs of patient ID and city such that the patient doesn't suffer from flu, and was treated in all the clinics in that city.
From what I've seen I need to divide the patients without flu by....? I think that it should be a table with all the clinics in a certain city, but how do I get that, and for each possible city?
Thanks

so... this is kind of complicated... pay special attention to the sample data I included in the tables.
http://sqlfiddle.com/#!2/04eac4/15/0
http://sqlfiddle.com/#!2/04eac4/17/0
I have no idea where division was supposed to take place...?
First we need to know how many clinics are in each city:
select city, count(cid) as c_count from clinic group by city
Then we need to know where each patient has been treated for anything besides the flu...
select patient.pid, patient.pname, clinic.city,
count(distinct clinic.cid) as p_c_count
from patient
join patient_doctor
on patient.pid = patient_doctor.pid
join doctor
on patient_doctor.did = doctor.did
join clinic
on doctor.cid = clinic.cid
where patient_doctor.disease not in ('Flu')
group by patient.pid, patient.pname, clinic.city
This joins all the tables together so that we can link PID and CID. Then we want only information that on patients that does not include a diagnosis of the flu. After, we group by the patient information and the clinic city so that we can count the number of clinics that patient went to for each city. Keep in mind, Patient A can go to Clinic 1 in the first city and be treated for the flu and even if he gets treated for the flu at a different clinic in a different city, the way you phrased the question allows that person to show up in results for the first city/clinic.... Does that makes any sense?
Then we need to join those two results. If the number of clinics in each city is equal to the number of clinics a patient visited per city, without being diagnosed with the flu, we get this:
select p_info.pid, c_ct_info.city
from (select city, count(cid) as c_count from clinic group by city) as c_ct_info
join (
select patient.pid, patient.pname, clinic.city,
count(distinct clinic.cid) as p_c_count
from patient
join patient_doctor
on patient.pid = patient_doctor.pid
join doctor
on patient_doctor.did = doctor.did
join clinic
on doctor.cid = clinic.cid
where patient_doctor.disease not in ('Flu')
group by patient.pid, patient.pname, clinic.city ) as p_info
on c_ct_info.city = p_info.city
where c_count = p_c_count;
Now. This excludes anyone who just visited one clinic and wasn't diagnosed with the flu but didn't go any of the other clinics in that city.
Just in case that sqlfiddle dies one day... here is the tables and data I used:
Create table Clinic (
CID int not null primary key,
Cname varchar(100),
Mname varchar(100),
Type tinyint,
City varchar(100)
);
insert into Clinic values (1,'Clinic 1','Mname 1', 1, 'City 1');
insert into Clinic values (2,'Clinic 2','Mname 2', 1, 'City 1');
insert into Clinic values (3,'Clinic 3','Mname 3', 1, 'City 2');
Create table Doctor (
DID int not null primary key,
Dname varchar(100),
Specialty varchar(100),
CID int,
foreign key (CID) references Clinic (CID)
);
insert into Doctor values (1, 'House', 'Internal Medicine', 1);
insert into Doctor values (2, 'Dr Who', 'General Practice', 1);
insert into Doctor values (3, 'Dr Dave', 'General Practice', 1);
insert into Doctor values (4, 'Dr Four', 'General Practice', 2);
insert into Doctor values (5, 'Dr Five', 'General Practice', 3);
insert into Doctor values (6, 'Dr Six', 'General Practice', 3);
create Table Patient (
PID int not null primary key,
PName varchar(100)
);
insert into Patient values (1, 'P. One');
insert into Patient values (2, 'P. Two');
insert into Patient values (3, 'P. Three');
insert into Patient values (4, 'P. Four');
insert into Patient values (5, 'P. Five');
Create table Patient_Doctor (
PDID int not null auto_increment primary key,
PID int not null,
DID int,
Disease varchar(100),
Severity tinyint,
foreign key (PID) references Patient (PID),
foreign key (DID) references Doctor (DID)
);
insert into Patient_Doctor values (null, 1, 1, 'Flu', 1);
insert into Patient_Doctor values (null, 1, 4, 'Flu', 1);
insert into Patient_Doctor values (null, 1, 5, 'Flu', 1);
-- shouldn't be in our results because they were diagnosed with the flu in each city
insert into Patient_Doctor values (null, 2, 2, 'Other', 1);
insert into Patient_Doctor values (null, 2, 4, 'Other', 1);
insert into Patient_Doctor values (null, 2, 5, 'Other', 1);
-- should be in our results because they attended every clinic in every city and
-- did not get diagnosed with the flu at any location
insert into Patient_Doctor values (null, 3, 1, 'Other', 1);
insert into Patient_Doctor values (null, 3, 4, 'Other', 1);
insert into Patient_Doctor values (null, 3, 6, 'Flu', 1);
-- should show up in our results for City 1 because they attended all the clinics in that
-- city and were not diagnosed with the flu. this person should NOT show up in our results
-- for city 2 because they were diagnosed with the flu at a clinic there.
insert into Patient_Doctor values (null, 4, 3, 'Other', 1);
-- should NOT show up in any results. although they weren't diagnosed with the flu, they
-- did not attend each clinic in that city.
insert into Patient_Doctor values (null, 5, 2, 'Flu', 1);
-- should NOT show up in results... meets none of the criteria
if we would add this data:
insert into Patient values (6, 'P. Six');
insert into Patient_Doctor values (null, 6, 5, 'Other', 1);
we should expect to see that person in our results because there's only one clinic in city 2 and they were not diagnosed with the flu there...
Things I changed:
Patient_Doctor: PID, DID, Disease, Severity
Patient: PID, PName
Clinic and Doctor are now joined by CID instead of CName
I highly suggest you create another table for Disease so that you are not repeating the same information over and over again. This table would include the fields Disease_ID and Disease_Description. The disease would then be linked to the patient by the Disease_ID.

Related

Query to find name of parents with age of youngest child

I have a table as such:
CREATE TABLE people
(
id INTEGER NOT NULL PRIMARY KEY,
motherId INTEGER,
fatherId INTEGER,
name VARCHAR(30) NOT NULL,
age INTEGER NOT NULL,
FOREIGN KEY (motherId) REFERENCES people(id),
FOREIGN KEY (fatherId) REFERENCES people(id)
);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (1, NULL, NULL, 'Adam', 50);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (2, NULL, NULL, 'Eve', 50);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (3, 2, 1, 'Cain', 30);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (4, 2, 1, 'Seth', 20);
I would like to write a query and get the name of the parents and the age of their youngest children. Not sure how to go about with this problem.
Expected output:
-- Expected output (in any order):
-- name age
-- ----------------------------
-- Adam 20
-- Eve 20
SELECT P1.name, P2.name, T.minAge
FROM (SELECT P.motherId, P.fatherId, MIN(AGE) AS minAge
FROM people P
GROUP BY P.motherId, P.fatherId) AS T JOIN people P1 ON T.motherId=P1.id
JOIN people P2 ON T.fatherId=P2.id
db<>fiddle

How to list total number of scholarships per department in SQL

I have 2 tables that look like this where I want to query how many scholarships (from Tuition table) each department (from Student table) has distributed:
I am thinking a join is necessary but am not sure how to do so.
Create tables
create table students (
sid int auto_increment primary key,
name varchar(100),
email varchar(100),
department varchar(100)
);
create table tutions (
id int auto_increment primary key,
sid int,
cost int,
scholarships int,
duedate timestamp default current_timestamp
);
Sample data
insert into students (name, email, department)
values
('John Doe', 'john#abc.xyz', 'B'),
('Jane Doe', 'jane#abc.xyz', 'A'),
('Jack Doe', 'jack#abc.xyz', 'C'),
('Jill Doe', 'jill#abc.xyz', 'B');
insert into tutions (sid, cost, scholarships)
values
(1, 1000, 2),
(2, 1000, 1),
(3, 1000, 7),
(4, 1000, 2);
Query (department-wise total scholarships)
SELECT department, sum(scholarships) as scholarships
FROM students s
JOIN tutions t ON s.sid = t.sid
GROUP BY department
Output
Running SQL Fiddle
Not sure It's something you want? And not sure scholarships is a number or name of scholarship? So I doubt it's a name as varchar string type.
### dummy record
CREATE TABLE students (
psu_id INTEGER PRIMARY KEY,
firstname VARCHAR NOT NULL,
lastname VARCHAR NOT NULL,
email VARCHAR NOT NULL,
department VARCHAR NOT NULL
);
CREATE TABLE tuition (
tuition_id INTEGER PRIMARY KEY,
student_id INTEGER NOT NULL,
semeter_cost INTEGER NOT NULL,
scholarships VARCHAR NOT NULL,
due_date DATE NOT NULL
);
INSERT INTO students VALUES (1, 'John', 'Hello', 'Jonh#email.com', 'Engineering');
INSERT INTO students VALUES (2, 'Bella', 'Fuzz', 'Bella#email.com', 'Computer');
INSERT INTO students VALUES (3, 'Sunny', 'World', 'Sunny#email.com', 'Science');
INSERT INTO tuition VALUES (1, 1, 4000, 'first_class_en', '2022-05-09' );
INSERT INTO tuition VALUES (2, 2, 3000, 'nobel', '2022-05-09' );
INSERT INTO tuition VALUES (3, 3, 5000, 'hackathon', '2022-05-09' );
INSERT INTO tuition VALUES (4, 1, 4500, 'second_class_en', '2022-05-09' );
-----------------
### query
SELECT s.department, count(t.scholarships)
FROM students s
JOIN tuition t
ON s.psu_id = t.student_id
GROUP BY s.department
### output
department, total_scholarships
Computer|1
Engineering|2
Science|1

Display User That Is Does Not Exist in Other Table

I have query that I am supposed to display The number of patients a physician can take on. He can have no more than 5 patients at a time. I have this query working with the following:
select PHYSICIAN.PHYSICIAN_ID,PHYSICIAN.firstname_physician,PHYSICIAN.lastname_physician, phone.phone_number, 5-count(patient.patient_id) as "Numbers of new patients he/she can take"
from patient, physician, physician_phone, phone
where physician.physician_id = patient.physician_id and PHYSICIAN_PHONE.PHYSICIAN_ID = PHYSICIAN.PHYSICIAN_ID and phone.PHONE_ID = physician_phone.PHONE_ID
group by PHYSICIAN.PHYSICIAN_ID, PHYSICIAN.firstname_physician, PHYSICIAN.lastname_physician, physician_phone.phone_id, phone.phone_number
having count(patient.patient_id)<5;
However this only displays the physicians that have patients not the physicians who have 0 patients connected to them.
My attempt to display the physicians who also have 0 patients was the following:
select PHYSICIAN.PHYSICIAN_ID,PHYSICIAN.firstname_physician,PHYSICIAN.lastname_physician, phone.phone_number, 5-count(patient.patient_id) as "Numbers of new patients he/she can take"
from patient, physician, physician_phone, phone
where physician.physician_id = patient.physician_id and PHYSICIAN_PHONE.PHYSICIAN_ID = PHYSICIAN.PHYSICIAN_ID and phone.PHONE_ID = physician_phone.PHONE_ID
group by PHYSICIAN.PHYSICIAN_ID, PHYSICIAN.firstname_physician, PHYSICIAN.lastname_physician, physician_phone.phone_id, phone.phone_number
having count(patient.physician_id)<5 OR NOT EXISTS ( Select patient.physician_id from patient Where patient.physician_id != physician.physician_Id group by patient.physician_id)
Below are the table creates to help anyone better understand the relationship between the tables
Create Table Physician (
Physician_ID integer not null,
Firstname_physician Char(30Char) not null,
lastname_physician Char(30Char) not null,
Constraint Physician Primary Key (Physician_ID));
Create Table Patient (
Patient_ID integer not null,
Patient_FirstName Char(20Char) not null,
Patient_LastName Char(20Char) not null,
Patient_MI Char(1Char) not null,
Patient_Gender Char(15Char) not null,
Staff_id integer not null,
Physician_ID integer not null,
Constraint Patient_pk Primary Key (Patient_ID),
Constraint HomeCareStaff_fk Foreign Key (Staff_ID) References HomeCareStaff(Staff_id),
Constraint Physician_ID_fk10 Foreign Key (Physician_ID) References Physician(Physician_ID));
Both tables queries return the same exact thing. Please see image results of query
Hope this makes sense Here are also the inserts
--populating Physician table--
insert into Physician values (100, 'Sasia', 'Applebottom');
insert into Physician values (101, 'Mac', 'Cheese');
insert into Physician values (102, 'Mick', 'Donalds');
insert into Physician values (103, 'Saint', 'West');
insert into Physician values (104, 'Chicago', 'West');
insert into Physician values (105, 'Mason', 'Disic');
---Populate Patient Table
insert into Patient values (150, 'Hayley', 'Beachump', 'F', 'Female', 50, 100);
insert into Patient values (151, 'Jacob', 'Stutzmen', 'K', 'Male', 51, 100);
insert into Patient values (152, 'Christina', 'Smush', 'P', 'Female', 52, 100);
insert into Patient values (153, 'Doris', 'Dorphish', 'D', 'Female', 53,100);
insert into Patient values (154, 'Adam', 'Wang', 'M', 'Male', 54, 100);
insert into Patient values (155, 'Levina', 'Reinhart', 'U', 'Female', 55, 101);
insert into Patient values (156, 'Harper', 'Mosbey', 'M', 'Male', 56, 102);
You can use this
select PHYSICIAN.PHYSICIAN_ID, PHYSICIAN.firstname_physician, PHYSICIAN.lastname_physician, phone.phone_number, count(patient.patient_id) as "Numbers of new patients he/she can take"
from patient, physician, physician_phone, phone
where physician.physician_id = patient.physician_id and PHYSICIAN_PHONE.PHYSICIAN_ID = PHYSICIAN.PHYSICIAN_ID and phone.PHONE_ID = physician_phone.PHONE_ID
group by PHYSICIAN.PHYSICIAN_ID, PHYSICIAN.firstname_physician, PHYSICIAN.lastname_physician, physician_phone.phone_id, phone.phone_number
having count(patient.patient_id) = 0;

What is wrong with this JOIN statement in SQL?

I am working on this tutorial about SQL. In Step 2 of 2, it is asked to use the JOIN command to link 2 people from the persons list using information from the friends list. I edited the provided code and obtained the code included below: the relevant part starts with select persons.fullname, persons2.fullname. However, the last paragraph of the code ('relevant code') does not yield any result nor error message. Am I doing something wrong?
Code
CREATE TABLE persons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fullname TEXT,
age INTEGER);
INSERT INTO persons (fullname, age) VALUES ("Bobby McBobbyFace", "12");
INSERT INTO persons (fullname, age) VALUES ("Lucy BoBucie", "25");
INSERT INTO persons (fullname, age) VALUES ("Banana FoFanna", "14");
INSERT INTO persons (fullname, age) VALUES ("Shish Kabob", "20");
INSERT INTO persons (fullname, age) VALUES ("Fluffy Sparkles", "8");
CREATE table hobbies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person_id INTEGER,
name TEXT);
INSERT INTO hobbies (person_id, name) VALUES (1, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (1, "coding");
INSERT INTO hobbies (person_id, name) VALUES (2, "dancing");
INSERT INTO hobbies (person_id, name) VALUES (2, "coding");
INSERT INTO hobbies (person_id, name) VALUES (3, "skating");
INSERT INTO hobbies (person_id, name) VALUES (3, "rowing");
INSERT INTO hobbies (person_id, name) VALUES (3, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (4, "coding");
INSERT INTO hobbies (person_id, name) VALUES (4, "dilly-dallying");
INSERT INTO hobbies (person_id, name) VALUES (4, "meowing");
CREATE table friends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person1_id INTEGER,
person2_id INTEGER);
INSERT INTO friends (person1_id, person2_id)
VALUES (1, 4);
INSERT INTO friends (person1_id, person2_id)
VALUES (2, 3);
/* personal contribution starts here
select persons.fullname,hobbies.name
from persons
join hobbies
on hobbies.person_id=persons.id;
/* select persons.fullname, persons2.fullname
from persons
join persons persons2
join friends
on persons.fullname=friends.person1_id and persons2.fullname=friends.person2_id; */
/* relevant code: */
select persons.fullname, persons2.fullname
from persons
join friends
on persons.fullname=friends.person1_id
join persons persons2
on persons2.fullname=friends.person2_id;
[tutorial (c) khanacademy.org]
join friends
on persons.fullname=friends.person1_id
You're only including friends whose person1_id equals a person's fullname. Since person1_id is an integer and fullname is text, those will never be equal. You probably want:
select persons.fullname, persons2.fullname
from persons
join friends
on persons.id=friends.person1_id
join persons persons2
on persons2.id=friends.person2_id;

convert marks into percentage

how to convert marks obtained by a student into x%
i.e. there are two exams. calculate certain %marks from both exams (say x% and Y%) so that the total will be 100%
Based on the limited info that you have provided, I think you might be asking for the following:
create table student
(
id int,
s_name varchar(10)
)
insert into student values (1, 'Jim')
insert into student values (2, 'Bob')
insert into student values (3, 'Jane')
create table exams
(
id int,
e_name varchar(10)
)
insert into exams values (1, 'Test 1')
insert into exams values (2, 'Test 2')
insert into exams values (3, 'Test 3')
insert into exams values (4, 'Test 4')
create table exam_student
(
e_id int,
s_id int,
dt datetime,
score decimal(5,2)
)
insert into exam_student values(1, 1, '2012-08-01', 65.0)
insert into exam_student values(1, 2, '2012-08-01', 85.0)
insert into exam_student values(2, 1, '2012-08-02', 75.0)
insert into exam_student values(2, 2, '2012-08-02', 42.0)
select avg(es.score) as ScorePct, s_id, s.s_name
from exam_student es
inner join exams e
on es.e_id = e.id
inner join student s
on es.s_id = s.id
group by s_id, s_name
Results:
If you provide more details on exactly what you are looking for that would be helpful in answering your question.