I'm creating code that simulates patients going to the hospital to test for covid-19. I need to consult the youngest patient that tested positive (the patients only have different ages), but I can't get the information right about the patient (patient_name, codepatient). I've tried using subquery:
SELECT P.patient_name, P.patient_age, T.results
FROM patient P
LEFT OUTER JOIN testing T on T.codepatient=P.codepatient
WHERE P.patient_age =
(SELECT min(P.patient_age)
FROM patient P);
But I can't find a way to retrieve the testing = 'Positive'. I also tried this:
SELECT P.patient_name, min(P.patient_age), T.results, T.codepatient
FROM patient P
INNER JOIN testing T on T.codepatient=P.codepatient
WHERE T.results = 'Positive';
Unfortunately it shows only the right age, the name and code are selected from the oldest patient.
I'm a college student and I'm beginning to use MySQL. English is my second language, i'm trying my best to ask this question clearly, i apologize if i make mistakes.
You can include the test for Positive in the subselect:
SELECT p.patient_name, p.patient_age, t.results
FROM patient p
INNER JOIN testing t
on t.codepatient = p.codepatient
WHERE p.patient_age = (SELECT min(p.patient_age)
FROM patient p
INNER JOIN testing t
ON t.codepatient = p.codepatient
WHERE t.results = 'Positive');
db<>fiddle here
You need to order the data by age, then use LIMIT 1 to get one record
SELECT P.pacient_name, P.pacient_age, T.results, T.codepacient
FROM pacient P
INNER JOIN testing T on T.codepacient=P.codepacient
WHERE T.results = 'Positive' ORDER BY p.pacient_age LIMIT 1
Related
I am having some problems with this homework question:
I have been able to successfully complete almost all of the query except for the "Only include states with at least 3 diamond mines". I would like to ask how I can add this part to the query.
select I.state, sum(P.capacity)
from Infrastructure I
natural join Mine M
join produces P
on P.mine = M.entryno
join Commodity C
on C.comID = P.commodity
where C.name like '%Diamond%'
group by I.state
If your attempt works fine other than condition mentioned in question following query should work:
select I.state, sum(P.capacity)
from Infrastructure I
natural join Mine M
join produces P
on P.mine = M.entryno
join Commodity C
on C.comID = P.commodity
where C.name like '%Diamond%'
group by I.state
having count(P.mine) >=3;
It will count the no. of commodity for each state as you already has group by on State.
Hope it helps!
Use a HAVING clause to count and assert the number of diamond mines:
SELECT
I.state,
SUM(P.capacity)
FROM Infrastructure I
NATURAL JOIN Mine M
INNER JOIN produces P
ON P.mine = M.entryno
INNER JOIN Commodity C
ON C.comID = P.commodity
WHERE
C.name LIKE '%Diamond%'
GROUP BY
I.state
HAVING
COUNT(*) >= 3;
Note: Natural join seems error prone to me and could break at some point. The best thing to use are explicit joins.
I'm really struggling with this query and I hope somebody can help.
I am querying across multiple tables to get the dataset that I require. The following query is an anonymised version:
SELECT main_table.id,
sub_table_1.field_1,
main_table.field_1,
main_table.field_2,
main_table.field_3,
main_table.field_4,
main_table.field_5,
main_table.field_6,
main_table.field_7,
sub_table_2.field_1,
sub_table_2.field_2,
sub_table_2.field_3,
sub_table_3.field_1,
sub_table_4.field_1,
sub_table_4.field_2
FROM main_table
INNER JOIN sub_table_4 ON sub_table_4.id = main_table.id
INNER JOIN sub_table_2 ON sub_table_2.id = main_table.id
INNER JOIN sub_table_3 ON sub_table_3.id = main_table.id
INNER JOIN sub_table_1 ON sub_table_1.id = main_table.id
WHERE sub_table_4.field_1 = '' AND sub_table_4.field_2 = '0' AND sub_table_2.field_1 != ''
The query works, the problem I have is sub_table_1 has a revision number (int 11). Currently I get duplicate records with different revision numbers and different versions of sub_table_1.field_1 which is to be expected, but I want to limit the result set to only include results limited by the latest revision number, giving me only the latest sub_table_1_field_1 and I really can not figure it out!
Can anybody lend me a hand?
Many Thanks.
It's always important to remember that a JOIN can be on a subquery as well as a table. You could build a subquery that returns the results you want to see then, once you've got the data you want, join it in the parent query.
It's hard to 'tailor' an answer that's specific to you problem, as it's too obfuscated (as you admit) to know what the data and tables really look like, but as an example:
Say table1 has four fields: id, revision_no, name and stuff. You want to return a distinct list of name values, with their latest version of stuff (which, we'll pretend varies by revision). You could do this in isolation as:
select t.* from table1 t
inner join
(SELECT name, max(revision_no) maxr
FROM table1
GROUP BY name) mx
on mx.name = t.name
and mx.maxr = t.revision_no;
(Note: see fiddle at the end)
That would return each individual name with the latest revision of stuff.
Once you've got that nailed down, you could then swap out
INNER JOIN sub_table_1 ON sub_table_1.id = main_table.id
....with....
INNER JOIN (select t.* from table1 t
inner join
(SELECT name, max(revision_no) maxr
FROM table1
GROUP BY name) mx
on mx.name = t.name
and mx.maxr = t.revision_no) sub_table_1
ON sub_table_1.id = main_table.id
...which would allow a join with a recordset that is more tailored to that which you want to join (again, don't get hung up on the actual query I've used, it's just there to demonstrate the method).
There may well be more elegant ways to achieve this, but it's sometimes good to start with a simple solution that's easier to replicate, then simplify it once you've got the general understanding of the what and why nailed down.
Hope that helps - as I say, it's as specific as I could offer without having an idea of the real data you're using.
(for the sake of reference, here is a fiddle with a working version of the above example query)
In your case where you only need one column from the table, make this a subquery in your select clause instead of than a join. You get the latest revision by ordering by revision number descending and limiting the result to one row.
SELECT
main_table.id,
(
select sub_table_1.field_1
from sub_table_1
where sub_table_1.id = main_table.id
order by revision_number desc
limit 1
) as sub_table_1_field_1,
main_table.field_1,
...
FROM main_table
INNER JOIN sub_table_4 ON sub_table_4.id = main_table.id
INNER JOIN sub_table_2 ON sub_table_2.id = main_table.id
INNER JOIN sub_table_3 ON sub_table_3.id = main_table.id
WHERE sub_table_4.field_1 = ''
AND sub_table_4.field_2 = '0'
AND sub_table_2.field_1 != '';
This question is continue of this here, since they don't want to answer without opening new.
This is my tables:
customer_profiles
friend_levels
so I have a query that get what level he's from, so when he got points = 168 then he will getGreat Friend so this is the SQL that I've already have.
SELECT s.*
FROM customer_profiles t
INNER JOIN friend_levels s ON(t.friend_points >= s.points_needed)
WHERE s.points_needed = (SELECT max(f.points_needed)
FROM friend_levels f
WHERE t.friend_points >= f.points_needed)
AND t.user_id = $user_id
and result like this
so my question is how to get the next value of it in order to use it like this? For ex. If I am on the Great Friend level, then I have to get the Best Friend level.
This should be simple:
SELECT (SELECT min(fl.points_needed)
FROM friend_levels fl
WHERE fl.points_needed > cp.friend_points) - cp.friend_points AS points_needed_for_next_level
FROM customer_profiles cp
WHERE cp.user_id = $user_id;
I have a query that retrieve information from 5 tables. The relation between them is showed in the picture attached. I have created a query to do this, and so far so good. The issue is each user can have 1 or more entries at "PROFISSIONAL_PORCENTAGEM" table. My query is retrieving all them. I want the last one based on the date field "PROFISSIONAL_PORCENTAGEM_DATA". I´ve performed a research about this issue and the solution of "retrieve the most recent of each id" is the same when we are using only one table see example here MySQL - Selecting the most recent post by each of the 10 most recent authors. But in this case I have 5 tables. I dont know how to do that. Any idea will be appreciated.
SELECT
PP.PROFISSIONAL_PORCENTAGEM_Pk,
UST.USER_NAME,
ADDR.ADDRESS_NOME,
ADDR.ADDRESS_ATIVO,
PA.PROFESSIONAL_ADDRSS_PK,
PP.PROFISSIONAL_PORCENTAGEM_PORCENT,
PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA,
PP.PROFISSIONAL_PORCENTAGEM_DATA
FROM
profissional_porcentagem AS PP
RIGHT JOIN professional_addrss AS PA
ON(PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA=PA.PROFESSIONAL_ADDRSS_PK)
INNER JOIN address ADDR
ON(PA.PROFESSIONAL_ADDRSS_FKADDRSS=ADDR.ADDRESS_Pk)
INNER JOIN professional PF
ON(PA.PROFESSIONAL_ADDRSS_FKPROFESSIONAL=PF.PROFESSIONAL_Pk)
INNER JOIN usert AS UST
ON(PF.PROFESSIONAL_FKUSER=UST.USER_Pk)
WHERE UST.USER_Pk=3
AND ADDR.ADDRESS_ATIVO=1;
sorry I need 10 reputation to attach image!!
This is the image link http://imgur.com/ZP3OdeX
Well, finally I found the solution.
Just add this code to the end of sql query:
AND PP.PROFISSIONAL_PORCENTAGEM_Pk = (
SELECT t2.PROFISSIONAL_PORCENTAGEM_Pk FROM profissional_porcentagem as t2
where t2.PROFISSIONAL_PORCENTAGEM_FK_CLINICA = PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA
order by t2.PROFISSIONAL_PORCENTAGEM_Pk desc limit 1
)
And then we gonna have the entire query like this:
SELECT
PP.PROFISSIONAL_PORCENTAGEM_Pk,
UST.USER_NAME,
ADDR.ADDRESS_NOME,
ADDR.ADDRESS_ATIVO,
PA.PROFESSIONAL_ADDRSS_PK,
PP.PROFISSIONAL_PORCENTAGEM_PORCENT,
PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA,
PP.PROFISSIONAL_PORCENTAGEM_DATA
FROM
profissional_porcentagem AS PP
RIGHT JOIN professional_addrss AS PA
ON(PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA=PA.PROFESSIONAL_ADDRSS_PK)
INNER JOIN address ADDR
ON(PA.PROFESSIONAL_ADDRSS_FKADDRSS=ADDR.ADDRESS_Pk)
INNER JOIN professional PF
ON(PA.PROFESSIONAL_ADDRSS_FKPROFESSIONAL=PF.PROFESSIONAL_Pk)
INNER JOIN usert AS UST
ON(PF.PROFESSIONAL_FKUSER=UST.USER_Pk)
WHERE UST.USER_Pk=3
AND ADDR.ADDRESS_ATIVO=1
AND PP.PROFISSIONAL_PORCENTAGEM_Pk = (
SELECT t2.PROFISSIONAL_PORCENTAGEM_Pk FROM profissional_porcentagem as t2
where t2.PROFISSIONAL_PORCENTAGEM_FK_CLINICA = PP.PROFISSIONAL_PORCENTAGEM_FK_CLINICA
order by t2.PROFISSIONAL_PORCENTAGEM_Pk desc limit 1
);
Note: I was inspired by this post Select row with most recent date per user
I have a database storing various information about fictional people. There is a table person with general information, such as name, adress etc and some more specific tables holding health history and education for everyone.
What I'm trying to do now, is getting possible connections for one person based on similarities like being at the same school for the same time or having the same doctor or being treated in the same hospital at the same time.
Following Query works fine for this (:id being the id of the person in question), however it is horribly slow (takes about 6secs to get a result).
SELECT person.p_id as id, fname, lname, image FROM person WHERE
(person.p_id IN (
SELECT patient from health_case WHERE
doctor IN (SELECT doctor FROM health_case WHERE patient =:id )
OR center IN (SELECT hc2.center FROM health_case as hc1, health_case as hc2 WHERE hc1.patient = :id AND hc2.center = hc1.center AND (hc1.start <= hc2.end AND hc1.end >= hc2.start)))
OR person.p_id IN (
SELECT ed2.pupil FROM education as ed1, education as ed2 WHERE
ed1.school IN (SELECT school FROM education WHERE pupil = :id) AND ed2.school = ed1.school AND (ed2.start <= ed1.end AND ed2.end >= ed1.start)
))
AND person.p_id != :id
What would be the best approach to convert it to use JOIN clauses? I somehow seem unable to wrap my head around these...
I think I understand what you're trying to do. There is more than one way to skin a cat, but may I suggest splitting your query into two separate queries, and then replacing the complicated WHERE clause with a couple inner joins? So, something like this:
/* Find connections based on health care */
SELECT p2.p_id as id, p2.fname, p2.lname, p2.image
FROM person p
JOIN health_case hc on hc.patient = p.p_id
JOIN health_case hc2 on hc2.doctor = hc.doctor and hc2.healthcenter = hc.healthcenter and hc.start <= hc2.end and hc.end >= hc2.start and hc2.patient <> hc.patient
JOIN person p2 on p2.p_id = hc2.patient and p2.p_id <> p.p_id
WHERE p.p_id = :id
Then, create a separate query to get connections based on education:
/* Find connections based on education */
SELECT p2.p_id as id, p2.fname, p2.lname, p2.image
FROM person p
JOIN education e on e.pupil = p.p_id
JOIN education e2 on e2.school = e.school and e2.start <= e.end AND e2.end >= e.start and e.pupil <> e2.pupil
JOIN person p2 on p2.p_id = e2.pupil and p2.p_id <> p.p_id
WHERE p.p_id = :id
If you really want the data results to be combined, you can use UNION since both queries return the same columns from the person table.
Depends on your SQL engine. Newer SQL systems that have reasonable query optimizers will most likely rewrite both IN and JOIN queries to the same plan. Typically, a sub-query (IN Clause) is rewritten using a join.
In simple SQL engines that may not have great query optimizers, the join should be faster because they may run sub-queries into a temporary in-memory table before running the outer query.
In some SQL engines that have limited memory footprint, however, the sub-query may be faster because it doesn't require joining -- which produces more data.