MySQL how to select what I need, most likely an inner join - mysql

A bit of a newbie question, probably an INNER JOIN with an "AS" statement, but I can't figure it out...
This is for a MYSQL based competition app. I want to select the "img_title" for both img_id1 and img_id2. I can't figure out how to do it and still see which title is assigned to the associated _id1 or _id2.
My tables:
competitions
comp_id
img_id1
img_id2
on_deck
img_id
img_title
Desired results:
comp_id | img_id1 | img_title1 |img_id2 | img_title2

You need a join for each image:
SELECT comp.comp_id, img1.img_id, img1.img_title, img2.img_id, img2.img_title
FROM competitions comp
INNER JOIN on_deck img1 ON img1.img_id = comp.img_id1
INNER JOIN on_deck img2 ON img2.img_id = comp.img_id2
LEFT JOIN if img_id1 or img_id2 can be NULL.

select comp_id, img_id1, b.img_title as img_title1,
img_id2, b2.img_title as img_title2
from competitions a
left outer join on_deck b on b.img_id = a.img_id1
left outer join on_deck b2 on b2.img_id = a.img_id2
switch let outer join to inner join if you want to exclude rows in competitions that do not have two matching img_ids

This query should give you the results you want. This also assumes that comp.img_id1 and comp.img_id2 are never NULL.
SELECT comp.comp_id
, comp.img_id1
, deck1.img_title AS img_title1
, comp.img_id2
, deck2.img_title AS img_title2
FROM competitions AS comp
JOIN on_deck deck1 ON comp.img_id1 = deck1.img_id
JOIN on_deck deck2 ON comp.img_id2 = deck2.img_id
If you have plan on having a NULL or empty string comp.img_id1 and/or comp.img_id2 fields, you'll need to do some left joins.

Related

Join 4 tables with specified column

I have this code:
SELECT A.UNITCODE, B.FORMATIONCODE, C.UPPERFORMATIONCODE, D.UPPERFORMATIONCODE
FROM UNIT AS A.UNITCODE
INNER JOIN FORMATION AS B.FORMATIONCODE
INNER JOIN UPPERFORMATION_UNIT AS C.UPPERFORMATION
INNER JOIN UPPERFORMATION AS D.UPPERFORMATIONCODE
WHERE UNITCODE='7000007'
Can you guys help me how to join 4 tables with specified column?
Assuiming the all 3 related tables have the same UNIT_ID for join with table UNIT
SELECT
A.UNITCODE
, B.FORMATIONCODE
, C.UPPERFORMATIONCODE
, D.UPPERFORMATIONCODE
FROM UNIT AS A
INNER JOIN FORMATION AS B ON B.FORMATIONCODE = A.UNIT_ID
INNER JOIN UPPERFORMATION_UNIT AS C. C.UPPERFORMATION = A.UNIT_ID
INNER JOIN UPPERFORMATION AS D D.UPPERFORMATIONCODE = A.UNIT_ID
WHERE UNITCODE='7000007'
It seems you are confusing table aliases and linking columns.
This is how to give a table an alias name in the query in order to enhance readability:
INNER JOIN formation AS f
where the AS is optional. Most often it is ommited.
This is how to join:
FROM unit AS u
INNER JOIN upperformation_unit AS ufu ON ufu.unitcode = u.unitcode
Well, I don't know the columns linking the tables of course, let alone their names. But I suppose the query would have to look like this more or less:
SELECT
u.unitcode,
f.formationcode,
uf.upperformationcode,
ufu.upperformationcode
FROM unit u
JOIN upperformation_unit ufu ON ufu.unitcode = u.unitcode
JOIN upperformation uf ON uf.upperformationcode = ufu.upperformationcode
JOIN formation f ON f.formationcode uf.formationcode
WHERE u.unitcode = 7000007;

use multiple results of a query within the query with joins

I have some tables in my database, three main ones and one that holds the many-to-many relations.
1. Student (student_id, student_name)
2. Sport (sport_id, sport_name)
3. Departm (depart_id, depart_name)
4. Sch (sch_id, sch_name)
5. StudSport(relationid, studendid, sportid, departid, schid)
What I want to do is e.g. retrieve the name of the department based on the relations when I know the id. I can get the ids like this:
SELECT departid, schid from studsport
inner join Student on student_id = studentid
inner join Sport on sport_id = sportid
where student_id = 1 and sport_id=2
but I want to get the names of the department and the Sch from their corresponding tables, and I dont know how to do that.
As you don't select anything from Student or Sport, you can remove the corresponding inner joins.
SELECT d.depart_name, sch.sch_name FROM StudSport s
INNER JOIN Sch sch ON s.schid = sch.sch_id
INNER JOIN Departm d ON s.departid = d.depart_id
WHERE s.studendid = 1 AND s.sportid = 2
Something like this???
select sch.sch_nam, departm.depart_name,
-- what you have already --
Left outer Join StudSport on Student.student_id = Studsport.studentid and Sport.sport_id = StudSport.sportid
left outer Join Sch on StudSport.schid = Sch.sch_id
left outer join Departm on studsport.depart_id = studsport.departid
This is untested, a fiddle makes it much easier to give answers because of that.
EDIT - I misread your original query - before the downvotes start to rain - fixing it right now.
The way you should use LEFT OUTER and INNER joins is how the data is meant (again, a fiddle will normally be usefull) but it's just a couple of joins from what you have i guess:
select *
from studsport
join student on studsport.studentid = student.student_id
join sport on studsport.sportid = sport.sport_id
left outer Join Sch on StudSport.schid = Sch.sch_id
left outer join Departm on studsport.depart_id = studsport.departid
where student_id = 1 and sport_id=2

Get only rows with max value having 5 tables

I have this query:
SELECT work_orders.id,work_orders.create_datetime,work_orders.location,
work_orders.description,user_accounts.function as function,
user_accounts.name as username,work_order_states.name as state,
work_orders_history.state_id,max(work_order_states.id)
FROM `work_orders`
LEFT JOIN work_orders_history
on work_orders.id = work_orders_history.work_order_id
LEFT JOIN user_accounts
on work_orders.create_user_id = user_accounts.id
LEFT JOIN work_order_type
on work_orders_history.type_id = work_order_type.id
LEFT JOIN work_order_states
on work_orders_history.state_id = work_order_states.id
... and the result is this:
But what i want is only get the rows with max state_id.
I already tried various queries, but this is the best result I can get.
EDIT: Since it's more than 65k results it's hard to provide a fiddle. The desireable result is like this image:
Thanks in advance.
You appear to be very close in your query. You need to add a GROUP BY and take away one of your select columns.
SELECT work_orders.id,work_orders.create_datetime,work_orders.location,
work_orders.description,user_accounts.[function] as [function],
user_accounts.name as username,work_order_states.name as state,
max(work_order_states.id)
FROM `work_orders`
LEFT JOIN work_orders_history
on work_orders.id = work_orders_history.work_order_id
LEFT JOIN user_accounts
on work_orders.create_user_id = user_accounts.id
LEFT JOIN work_order_type
on work_orders_history.type_id = work_order_type.id
LEFT JOIN work_order_states
on work_orders_history.state_id = work_order_states.id
GROUP BY work_orders.id,work_orders.create_datetime,work_orders.location,
work_orders.description,user_accounts.function,
user_accounts.name,work_order_states.name
HAVING work_orders_states.ID = (SELECT MAX(state_id) FROM work_orders_history)
I think what you are looking for is the HAVING and GROUP BY clause combined..
SELECT work_orders.id,work_orders.create_datetime,work_orders.location,
work_orders.description,user_accounts.function as function,
user_accounts.name as username,work_order_states.name as state,
work_orders_history.state_id,max(work_order_states.id)
FROM `work_orders`
LEFT JOIN work_orders_history
on work_orders.id = work_orders_history.work_order_id
LEFT JOIN user_accounts
on work_orders.create_user_id = user_accounts.id
LEFT JOIN work_order_type
on work_orders_history.type_id = work_order_type.id
LEFT JOIN work_order_states
on work_orders_history.state_id = work_order_states.id
GROUP BY work_orders.id,work_orders.create_datetime,work_orders.location,
work_orders.description,user_accounts.function,
user_accounts.name,work_order_states.name,
work_orders_history.state_id
HAVING work_orders_history.state_id=max(work_order_states.id)

Need some assistance with a complex JOIN is SQL Query

Take a look at these tables
It's simple: Venue contains country_ID which is an FK in Society_Territory where we will find a society_ID which is an FK of Society. I have a Venue_ID during the query and my objective is to get the Society_Name but there is a twist but first lets just get the Society_Name
In the following query only look at JOINS and in there I am gonna add comments with this // prefix
SELECT
uuid()AS `UUID`,
`pc`.`PRSClaimID` AS `prsclaimid`,
`a`.`LoginName` AS `loginname`,
`a`.`BandName` AS `bandname`,
`smartistdetails`.`LoginName` AS `createdbyloginname`,
`Society`.`Society_Name` AS societyName
count(
`smliveclaims`.`LiveclaimsID`
)AS `gigcount`
FROM `smprsliveclaimlink`
JOIN `smliveclaims` ON `smprsliveclaimlink`.`fkLiveClaimID` = `smliveclaims`.`LiveclaimsID`
// Here I have the Venue_ID from smliveclaims so i starting moving towards society name
JOIN Venue ON `smliveclaims`.fk_venueId = Venue.Venue_ID
JOIN Society_Territory ON Venue.Country_ID = Society_Territory.Country_ID
JOIN Society ON Society_Territory.Society_Id = Society.Society_ID
// Now from Society i can select the Society_Name which i am already doing in the query above
JOIN `smartistdetails` `a`
JOIN `smprsclaims` `pc` ON `a`.`ArtistID` = `pc`.`fkArtistID`
JOIN `smcategories` ON `pc`.`FK_CategoryID` = `smcategories`.`Id`
JOIN `smcategoriestype` ON `smcategories`.`fk_CategoryTypeId` = `smcategoriestype`.`Id`
JOIN `smartistdetails` ON `pc`.`CreatedBy` = `smartistdetails`.`ArtistID` AND `smprsliveclaimlink`.`fkPRSClaimID` = `pc`.`PRSClaimID`
GROUP BY
`a`.`LoginName`,
`a`.`BandName`,
`smcategories`.`Id`,
`smcategoriestype`.`CategoryType`,
`smartistdetails`.`LoginName`
All is cool till here. Now here is the TWIST
I will have Country_IDs in Venue which will not be in Society_Territory. And I still want to select them and instead of showing and actual Society_Name want to show a word such as "Other"
use a LEFT OUTER JOIN when you link VENUE with SOCIETY_TERRITORY and so on when you link SOCIETY_TERRITORY with SOCIETY
Pay attention: When you use a LEFT OUTER JOIN all tables depends by its must be linked with other LEFT OUTER JOIN because if you use INNER JOIN you cancel di effects on LEFT.
Edit:
SELECT
uuid()AS `UUID`,
`pc`.`PRSClaimID` AS `prsclaimid`,
`a`.`LoginName` AS `loginname`,
`a`.`BandName` AS `bandname`,
`smartistdetails`.`LoginName` AS `createdbyloginname`,
coalesce(`Society`.`Society_Name`, 'Other') AS societyName
count(`smliveclaims`.`LiveclaimsID`)AS `gigcount`
FROM `smprsliveclaimlink`
JOIN `smliveclaims`
ON `smprsliveclaimlink`.`fkLiveClaimID` = `smliveclaims`.`LiveclaimsID`
// Here I have the Venue_ID from smliveclaims so i starting moving towards society name
JOIN Venue ON `smliveclaims`.fk_venueId = Venue.Venue_ID
LEFT OUTER JOIN Society_Territory ON Venue.Country_ID = Society_Territory.Country_ID
LEFT OUTER JOIN Society ON Society_Territory.Society_Id = Society.Society_ID
// Now from Society i can select the Society_Name which i am already doing in the query above
JOIN `smartistdetails` `a`
JOIN `smprsclaims` `pc` ON `a`.`ArtistID` = `pc`.`fkArtistID`
JOIN `smcategories` ON `pc`.`FK_CategoryID` = `smcategories`.`Id`
JOIN `smcategoriestype` ON `smcategories`.`fk_CategoryTypeId` = `smcategoriestype`.`Id`
JOIN `smartistdetails` ON `pc`.`CreatedBy` = `smartistdetails`.`ArtistID` AND `smprsliveclaimlink`.`fkPRSClaimID` = `pc`.`PRSClaimID`
GROUP BY
`a`.`LoginName`,
`a`.`BandName`,
`smcategories`.`Id`,
`smcategoriestype`.`CategoryType`,
`smartistdetails`.`LoginName`
All your JOINs are INNER JOINs. The INNER keyword is optional in MySQL and frequently omitted (as in your example). Use a LEFT OUTER JOIN where required and amend your SELECT clause to include something like "COALESCE(Society_Name,'Other') Society_Name"

Conditional Aliasing with Multiple Lookups

Say that you have a table with two (or more) columns which link to another table:
house_history houses
--------------- --------
OwnerID HouseID
PreviousHouseID Address
CurrentHouseID
and you wanted to return data from each of those IDs:
---------------------------------------------------------------
|OwnerID| PreviousAddress | CurrentAddress |
---------------------------------------------------------------
(linked to PreviousHouseID) (linked to CurrentHouseID)
How would you go about doing that? (specifically I'm interested in using MySQL)
SELECT OwnerId, p.Address as PreviousAddress, c.Address as CurrentAddress
FROM house_history h
LEFT JOIN houses p ON h.PreviousHouseID = p.HouseID
LEFT JOIN houses c ON h.CurrentHouseID = c.HouseID
try this
SELECT hh.OwnerID,h1.Address,h2.Address
FROM house_history hh
LEFT JOIN house h1 ON h1.HouseId = hh.PreviousHouseID
LEFT JOIN house h2 ON h2.HouseId = hh.CurrentHouseID
Probably you may required LEFT JOIN insted of INNER JOIN because it works also when current and previous house is null
SELECT
house_history.OwnerID
, houses_previous.Address AS PreviousAddress
, houses_current.houses.Address AS CurrentAddress
FROM house_history
LEFT JOIN houses AS houses_current ON (house_history.CurrentHouseID = houses_current.HouseID)
LEFT JOIN houses AS houses_previous ON (house_history.PreviousHouseID = houses_previous.HouseID);