mysql - retrieving a value using sub-select - mysql

SELECT snr, nsname FROM type
WHERE snr in (SELECT snr FROM diet
WHERE foodnr in (SELECT foodnr FROM food WHERE foodtype = 'FISH' ));
there are more animals that eat the same kind of food BUT eat different types of food in my database, how do i get the animals that only eat that type of food and nothing else.
bah this is impossible to answer without my entire database i feel like an ass just asking this because its so vague but what i am trying to do is i need to filter out the animals that have more foodtypes besides FISH

JOIN the tables instead, like so:
SELECT t.snr, t.nsname
FROM type t
INNER JOIN diet d ON t.snr = d.snr
INNER JOIN food f ON t.foodnr = f.foodnr
WHERE t.foodtype = 'FISH'
GROUP BY t.foodtype
HAVING COUNT(DISTINCT t.foodtype) = 1;

Note I'm assuming the following about your schema:
TYPE: snr, nsname
DIET: snr, foodnr
FOOD: foodnr, foodtype
You can use a NOT EXISTS:
SELECT t.snr, t.nsname
FROM type t
INNER JOIN diet d ON t.snr = d.snr
INNER JOIN food f ON d.foodnr = f.foodnr
WHERE f.foodtype = 'FISH'
AND NOT EXISTS
(
SELECT 1
FROM diet dd
INNER JOIN food ff ON dd.foodnr = ff.foodnr
WHERE ff.foodtype <> 'FISH'
AND dd.snr = t.snr
)
Or you can use an anti-join pattern:
SELECT t.snr, t.nsname
FROM type t
INNER JOIN diet d ON t.snr = d.snr
INNER JOIN food f ON d.foodnr = f.foodnr AND f.foodtype = 'FISH'
LEFT OUTER JOIN diet dd ON t.snr = dd.snr AND f.foodnr <> dd.foodnr
WHERE f.foodtype = 'FISH'
AND dd.snr IS NULL

Related

SQL - return rows that do not have a certain value

looking for a bit of help here if possible?
I have the following query:-
On or database we have a table called Linkfile, in this table are "Types" all beginning with "YG". I need to return those rows that do not have the type of "YG8" but just cannot seem to do it. I know ill need to use a sub query but am stuck!
This is my code and the fields I need to return. I just need to only show those that do not have the lk.type of "YG8"
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
inner join linkfile lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016'
and lk.type like 'YG%' and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type
Use below query :
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type,lk.parent_object_ref
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
left join (select displayname, type,parent_object_ref from linkfile where lk.type like 'YG8%' )lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016' and lk.parent_object_ref is null
and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type;
I've used left join on linkfile with type like 'YG8%' and fetching the only records which are not matched
I think you can just replace the
lk.type like 'YG%'
with the following:
(lk.type >= 'YG' and lk.type <'YG8') or (lk.type > 'YG8' and lk.type <='YGZ')
this should accomplish what you are trying to do and also avoid using "like" which is less efficient (assuming you have an index on lk.type, at least).
You may refine this a bit by knowing which are the possible values of lk.type of course. I.e. what are the extremes for the YG "subtype"? YG00-YG99? YG-YGZ?
(Be especially careful if you may have YG81 or YG87 for example, because then my clause will not work properly... on the other hand if your YG subtype can have values like YG34 it would have been better to use YG08 instead of YG8)

Dual Table SQL Query Help Needed

I have been given two tables with the following data:
ANIMAL TABLE:
Registration_Number
Sex
PEDIGREE TABLE:
Ped_Registration_Number
Name
Sire_Number
I need to write a sql statement that tells me the Name of a bull and how many bull calves and how many heifer calves he has produced.
I have no idea where to even start or if this can even be done with the table set-up.
The 'Sex' column with either be 'B' for Bull or 'H' for Heifer. The Sire_Number tells us who the Sire (Bull) of the animal is. The Sire_Number and Registartion_Number will be correlated.
You can start from this query:
SELECT p.Name
FROM pedigree p
INNER JOIN animal a
ON a.Registration_Number = p.Ped_Registration_Number
AND a.Sex = 'B'
that will returns you names of all bulls.
And here is the number of heifer calves portion:
SELECT p.Name,
COUNT(DISTINCT calves.Ped_Registration_Number) calves_number
FROM pedigree p
INNER JOIN animal a
ON a.Registration_Number = p.Ped_Registration_Number
AND a.Sex = 'B'
LEFT JOIN pedigree calves
ON p.Ped_Registration_Number = calves.Sire_Number
GROUP BY p.Ped_Registration_Number
And the very last approach:
SELECT p.Name,
SUM(IF(h_b.sex='B',1,0)) calves_b,
SUM(IF(h_b.sex='H',1,0)) calves_h,
FROM pedigree p
INNER JOIN animal a
ON a.Registration_Number = p.Ped_Registration_Number
AND a.Sex = 'B'
LEFT JOIN pedigree calves
ON p.Ped_Registration_Number = calves.Sire_Number
LEFT JOIN a h_b
ON calves.Ped_Registration_Number = h_b.Registration_Number
GROUP BY p.Ped_Registration_Number
SELECT p.Name,
SUM(IF(h_b.sex='B',1,0)) calves_b,
SUM(IF(h_b.sex='H',1,0)) calves_h,
FROM pedigree p
INNER JOIN animal a
ON a.Registration_Number = p.Ped_Registration_Number
AND a.Sex = 'B'
LEFT JOIN pedigree calves
ON p.Ped_Registration_Number = calves.Sire_Number
LEFT JOIN a h_b
ON calves.Ped_Registration_Number = h_b.Registration_Number
GROUP BY p.Ped_Registration_Number

SQL different condition multi select

What I want to do (for each flight), is to select Flight_number, Departure_airport' s Name And Arrival_airport' s Name . Departure has MIN Leg_number, Arrival has MAX Leg_number.
I have tried this. But join parts or what else missing, here is the link:http://sqlfiddle.com/#!2/263a2/5
Seems odd.. but this might be what you're after...
We get the min/max leg for each flight in subquery aliased "Z"
We use this to join back to flight_leg twice, once for departure and once for arrivals
and again join back twice to airport once for departures once for arrivals.
SELECT Z.Flight_Number, DA.Name DeptName, AA.Name ArrivName
FROM (SELECT MIN(Leg_Number) MLN, MAX(Leg_Number) MxLN, Flight_Number
FROM Flight_Leg Group by Flight_Number) Z
INNER JOIN Flight_Leg D
on D.Flight_Number = Z.Flight_Number
and D.Leg_Number = Z.MLN
INNER JOIN Flight_Leg A
on A.Flight_Number = Z.Flight_Number
and A.Leg_Number = Z.MxLN
INNER JOIN AirPort DA
on DA.AirPort_Code = D.Departure_AirPort_Code
INNER JOIN AirPort AA
on AA.AirPort_Code = A.Arrival_AirPort_Code
http://sqlfiddle.com/#!2/263a2/56
Not entirely sure if this is what you're after. It's written in MS SQL so the syntax will need some minor tweaks.
SELECT fl.Flight_number,
ao.Name,
ai.Name,
(select min(Leg_number) from FLIGHT_LEG fa where fl.Flight_number
= fa.Flight_number) as min_leg_number,
(select max(Leg_number) from FLIGHT_LEG fb where fl.Flight_number
= fb.Flight_number) as max_leg_number
FROM Flight_leg Fl
inner join AIRPORT as ao on fl.Departure_airport_code =
ao.Airport_code
inner join AIRPORT as ai on fl.Arrival_airport_code =
ai.Airport_code

Selecting from different tables based on condition

I Have a table comments ->
id | comment | type | userid |
1 Hello human 9
2 Hi robot 4
3 Gnaw! animal 1
4 Boo ghost 2
Also i have four more tables human,robot,ghost and animal
These tables contains some basic details about themselves...
Now I have a know value of comment say : $id = 3
if i do
$data = mysqli_query($con,"SELECT type FROM comments WHERE id = $id");
while($row = mysqli_fetch_assoc($data)){
$table = $row['type'];
$table_data = mysqli_fetch_assoc(mysqli_query($con,"SELECT * FROM $table"));
}
this will fetch me all the data about the one who commented but this will prove to be too slow....is there any way i can combine this in one single query ?
One way to do this is with left joins.
SELECT c.type, COALESCE(h.detail,r.detail,a.detail,g.detail)
FROM comments
LEFT JOIN human h ON c.type = 'human' AND c.id = h.id
LEFT JOIN robot r ON c.type = 'robot' AND c.id = r.id
LEFT JOIN animal a ON c.type = 'animal' AND c.id = a.id
LEFT JOIN ghost g ON c.type = 'ghost' AND c.id = g.id
Another way would be to do a UNION on the four tables and then join those:
SELECT c.type, q1.detail
FROM comments c
LEFT JOIN
(
SELECT 'human' AS type, detail FROM human
UNION
SELECT 'robot', detail FROM robot
(etc.)
) q1 ON c.type = q1.type AND q1.id = c.id
I would prefer the second option, because this one makes it easier to join lots of detail-columns. I don't think there's much of a difference perfomance-wise.

SQL/MySQL Query Assitance

I'm writing a query to list the first and last names of all staff who have ever taught any of the same course as Kim (Staff_Fname) Cox (Staff_Lname) or have ever taught in the same room (Loc_id) as Kim Cox.
So far I have written this (and it's full of errors):
SELECT KimClasses.Course_Code, KimClasses.Course_Name, St2.Staff_Fname, St2.Staff_Lname
FROM
(SELECT St.Staff_id, CS.C_SE_id, C.Course_code, C.Course_name
FROM Staff St
JOIN CourseSection CS ON St.Staff_id = CS.Staff_ID
JOIN Location L ON CS.Loc_ID = L.Loc_id
JOIN Course C ON CS.Course_ID = C.Course_ID
WHERE St.Staff_Fname = "Kim"
AND St.Staff_Lname = "Cox") KimClasses
JOIN CourseSection CS2 ON KimClasses.Course_ID = CS2.Course_ID
AND NOT KimClasses.Staff_id = St2.Staff_id;
But I'm not sure on how I would include the part to list the staff that have taught in the same room.
Database schema: http://i.stack.imgur.com/dTGV5.jpg
This should get you started...
Select s.staff_fname,s.staff_lname
from staff s join course_section cs
on s.staff_if = cs.staff_id
where cs.course_id in (select distinct s1.course_id from staff s1 join course_section sc1 where s1.Staff_Fname = 'kim' and s1.Staff_Lname = "Cox" )
OR s.loc_id in (select distinct s2.loc_id from staff s2 join course_section sc2 where s2.Staff_Fname = 'kim' and s2.Staff_Lname = "Cox" )