opinion about a query - mysql

If I have this piece of schema:
Doctor(license_no, doctor_name, specialty)
Patient(pat_id, pat_name, pat_address, pat_phone, date_of_birth)
Visit(license_no, pat_id, date, type, diagnosis, charge)
and I want to get the amount of money that Dr. Davy Jones has earned,
is the following query logically right? N.B it's running in SQL
SELECT SUM(charge)
FROM Visit v INNER JOIN Doctor d
ON (d.licence_no = v.licence_no AND doctor_name = 'davy jones')

I'd write it slightly different to account for the case where davy jones has seen no patients.
SELECT SUM(v.charge)
FROM Doctor d
LEFT JOIN Visit v
ON d.license_no = v.license_no
WHERE d.doctor_name = 'davy jones';

Yes :)
Just made a quick test.

Since you alias the table "Visit" to "v" you should also use the alias when specifying the column (v.charge). Also your inner join condition should specify only the join condition, and not the limiting clause, which should be specified as a WHERE condition. See this example:
SELECT SUM(v.charge)
FROM Visit v INNER JOIN Doctor d
ON (d.licence_no = v.licence_no)
WHERE d.doctor_name = 'davy jones';

Related

Using select from another select in MySQL

I have the following query where I will have finally a 205 patient IDs to work with:
select
patient_id
FROM
visit
WHERE
month(visit.date_of_visit)=3
AND
year(visit.date_of_visit)=2018
AND
visit.visit_status='Active'
GROUP BY patient_id
I want to get all the 205 IDs and run them into other query to see how many diseases we have as cardio-vascular and then as respiratory disease.
My database structure is as the following:
What I want is to get for each patient id, what they are diagnosed at ONLY their first visit to the hospital (so here we will work with min(visit.date_of_visit))
The desired result for `diagnosis_name LIKE '%Cardio%':
E.g>:
Patients: 150 (Or something)
And the query is changed to get the respiratory info.
I tried the following for the Cardio diseases where I use select from select:
SELECT count(*)
FROM
(
select
min(visit.date_of_visit), visit_id, patient_id, count(*) as patientId
FROM
visit
WHERE
month(visit.date_of_visit)=3
AND
year(visit.date_of_visit)=2018
AND
visit.visit_status='Active'
GROUP BY patient_id
) as vid
LEFT JOIN
consultation ON consultation.visit_id=vid.visit_id
LEFT JOIN
diagnosis ON diagnosis.diagnosis_id=consultation.diagnosis_id
WHERE diagnosis.diagnosis_name LIKE '%Cardio%'
The result was: 5 which is a wrong number.
This can be done easily with PHP and MYSQL together but this will exhaust the server by repeating the same query for 205 times and increment a counter. So the desired result should be only done with MySQL.
Data example:
Visit Table
visit_id= 1; date_of_visit=2018-03-03; visit_reason=Active; ...;
patient_id=1234;
visit_id= 2; date_of_visit=2018-03-04; visit_reason=Active; ...;
patient_id=1239;
visit_id= 3; date_of_visit=2018-03-07; visit_reason=Active; ...;
patient_id=1234;
Consultation Table
consultation_id=1; ...; diagnosis_id=12; visit_id=1;...;
consultation_id=2; ...; diagnosis_id=12; visit_id=2;...;
Diagnosis Table
diagnosis_id=12; diagnosis_name: hypertension (cardio disease);
diagnosis_id=13; diagnosis_name: renal disease
By running the query to see patients who came to hospital and that they were diagnosed as having cardio disease in their initial first visit, the result should be in the example as 2 as you can see from the example where patient_id=1234 had 2 visits but I need to know what he had in his first one.
You can use window functions in MySQL 8+. But in older versions you need to calculate the value some other way.
The question for you is what you are counting:
SELECT COUNT(*) as num_diagnoses, COUNT(DISTINCT patient_id) as num_patients
FROM visit v JOIN
(SELECT patient_id,
MIN(v.date_of_visit) as min_dov
FROM visit v
WHERE v.date_of_visit >= '2018-03-01' AND
v.date_of_visit < '2018-04-01' AND
v.visit_status = 'Active'
) vf
ON v.patient_id = vf.patient_id AND v.date_of_visit = vf.min_dov JOIN
consultation c
ON c.visit_id = v.visit_id JOIN
diagnosis d
ON d.diagnosis_id = c.diagnosis_id
WHERE d.diagnosis_name LIKE '%Cardio%';
When working with dates, it is best to compare column values directly to dates, rather than dissecting them.
BRO, it works fine. Test it now on the live scenario.
SELECT count(*)
FROM
(
select
min(visit.date_of_visit) first_date, patient_id, count(*) as patientId
FROM
visit
WHERE
month(visit.date_of_visit)=3
AND
year(visit.date_of_visit)=2018
AND
visit.visit_status='Active'
GROUP BY patient_id
) as vid
INNER JOIN visit b ON
B.patient_id = vid.patient_id AND
B.date_of_visit = vid.first_date and
month(B.date_of_visit)=3 AND
year(B.date_of_visit)=2018 AND
B.visit_reason='Active'
INNER JOIN consultation ON
consultation.visit_id = B.visit_id
INNER JOIN diagnosis ON
diagnosis.diagnosis_id = consultation.diagnosis_id AND
diagnosis.diagnosis_name LIKE '%Cardio%'

SQL: SELECT where 2 columns from different tables are the same

I need to work with a database that contains info about (former) Presidents. I need to check if there a presidents that have the same hobbies AND are married in the same year.
So a president can have multiple hobbies in pres_hob table. And the marriage year is in the pres_mar table, in the mar_year column.
I've tried to INNER JOIN the tables in SQLite where the hobby and mar_year are equal, except for the pres_name. This way the JOIN doesnt work ofcourse, which makes sense. Im kinda new to this..
Any help is appreciated
Here's one option with multiple joins:
select p1.pres_name, p2.pres_name, ph.hobby
from pres_mar p1
join pres_mar p2 on p1.pres_name != p2.pres_name and p1.mar_year = p2.mar_year
join pres_hob ph on p1.pres_name = ph.pres_name
join pres_hob ph2 on p2.pres_name = ph2.pres_name and ph.hobby = ph2.hobby
And depending on your expected results, another option using exists:
select pm.pres_name, ph.hobby
from pres_mar pm
join pres_hob ph on pm.pres_name = ph.pres_name
where exists (
select 1
from pres_mar pm2
join pres_hob ph2 on pm2.pres_name = ph2.pres_name
where pm.pres_name != pm2.pres_name and
ph.hobby = ph2.hobby
)
That sounds like a terrible database schema, I'm assuming its for learning purposes, anyway, you could do something like
SELECT
h.name,
h.hobby,
m.year
FROM
pres_hob h,
pres_mar m
WHERE
h.hobby = 'tennis'
AND
m.year = 2016
This would return 1 record for every president with a marriage year of 2016 , and a hobby of Tennis.

How to get multi columns via subquery?

I want to get members and their photos. Every member has 2 photos. (I am not talking about profile image)
There are 2 tables named as Members and MemberPhotos.
Here is my query which doesn't work(expectedly):
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 1
) as MemberFirstPhoto,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 0
) as MemberSecondPhoto,
FROM
Members M
Maybe somebody going to say that I should use inner join instead, I don't want to use inner join, if I use it I get data multiple like:
Name Surname PhotoName
Bill Gates bill.png
Bill Gates bill2.png
Steve Jobs steve.jpg
Steve Jobs steve2.jpg
What do you recommend me about query?
Thanks.
EDIT:
Here is the output I want to get:
Name Surname FirstPhoto SecondPhoto
Bill Gates bill.png bill2.png
Steve Jobs steve.jpg steve2.png
The only issue with your example query is that you have an extra comma after
as MemberSecondPhoto
If you remove this it works fine.
SQL Fiddle with demo.
However, while that query is working now, because you know that each member only has two photos, you can use a much simpler query:
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
MPF.PhotoName as MemberFirstPhoto,
MPS.PhotoName as MemberSecondPhoto
FROM Members M
LEFT JOIN MemberPhotos MPF ON M.ID = MPF.MemberID AND MPF.IsFirst = 1
LEFT JOIN MemberPhotos MPS ON M.ID = MPS.MemberID AND MPS.IsFirst = 0
SQL Fiddle with demo.

Where clause in Query

My query looks like this. Suppose it was run well.im confused the last part of the Where clause.Can i write that from two different table?..how can i write it, cause i want to display those staff who a Active from that date range.
select d.Division,a.FirstName,
(select count(h.id) from Department h
inner join institution i on d.institution_id = i_Id
----
----
where i.institution_id =d.Id and h. date between #startDate and #endDate) as test
from Division d, inmate a
where d.Active = 1 and a.Active = 1
edited
i have edit my query and the final looks like this..
select d.DivisionName,a.FirstName, (select count(h.id) from InHistory h inner join Institution i on h.Institution_id = i.Id inner join InType it on h.InType_id = it.Id inner join mate a on h.mate_id = a.Id where i.InstitutionRegion_id = d.Id and it.InTypeName like '%Staff%' and h.AdmissionDate between '18/02/2013' and '18/02/2013') as Admission from Division d, mate a where d.Active= 1 and a.Active =1
Yes, you can give comparison between any number of tables in where clause provided you are giving valid conditions inside your where clause. I think you should refer SQL JOINS
You can add as many as you want clauses inside the WHERE from your SQL query..
see an example
SELECT *
FROM employee inner join department on
employee.DepartmentID = department.DepartmentID;
WHERE
employee.active = TRUE AND
department.group = 3
http://en.wikipedia.org/wiki/Join_(SQL)#Inner_join

I need to finalize this MySQL multiple table JOIN

I have entires, equipments, brands, times and seasons.
entries:
id
time
equipment_1
equipment_2
equipments:
id
id_brand
brands:
id
name
times:
id
id_season
seasons:
id
name
My actual SQL query is:
SELECT entries.*, times.id_season AS id_season
FROM entries, seasons
WHERE entries.time = times.id
But in the final query I need the next information that I don't know how to obtain it:
The name for each entries.equipment_ as equipment_1_name and equipment_2_name which is set in brands.name.
The name of the season as season_name.
Thank you in advance!
Assuming you have normalized data. This avoid costly cartesian joins. I never use cartesian joins myself, although there are some cases where they are useful. Not here, though.
SELECT
entries.*,
times.id_seasons AS id_season,
b1.name AS equipment_1_name,
b2.name AS equipment_2_name,
seasons.name AS season_name
FROM entries
LEFT JOIN equipments AS equipments_1
ON equipments_1.id = entries.equipment_1
LEFT JOIN brands AS brands_1
ON brands_1.id = equipments_1.id_brand
LEFT JOIN equipments AS equipments_2
ON equipments_2.id = entries.equipment_2
LEFT JOIN brands AS brands_2
ON brands_2.id = equipments_2.id_brand
LEFT JOIN times
ON times.id = entries.time
LEFT JOIN seasons
ON seasons.id = times.id_season;