MySQL - Join two rows to two columns - mysql

I have two tables: user and photo. They look like this:
I need to perform a SELECT on the user table based on uuid, returning the url for both profile_photo and background_photo, if they exist.
These are essentially the final fields I need (the last two being JOINed from photo):
user.name, user.profile_photo_url, user.background_photo_url
WHERE user.uuid = SOME_UUID
Can somebody point me in the right direction with this statement?

SELECT user.name, photo_a.url AS profile_photo_url, photo_b.url as background_photo_url FROM user LEFT JOIN photo as photo_a ON user.profile_photo_uuid = photo_a.uuid LEFT JOIN photo as photo_b ON user.background_photo_uuid = photo_b.uuid WHERE user.uuid = SOME_ID

This should work for you
SELECT u.name,u.profile_photo_uuid,u.background_photo_url FROM user u, photo p
WHERE u.uuid = **userid** AND
( p.uuid = u.profile_photo_uuid OR p.uuid = u.background_photo_url);

Related

How to get data from two tables from database with MySql

What I want to do is to get all of the information from one table where the username and the number is the same as in the table, and then on the same call I want to join two rows from a different table with the same title as the first table row named "title" (hopefully I got it clear enough).
Tried this:
`SELECT * FROM movies_in_theater
WHERE username = "${req.username}"
AND theater_number = '${req.theater}'
LEFT JOIN movie_info.key_exp, movie_info.key_exp_time
WHERE movies_in_theater.movie_title = movie_info.title
`
Like this:
SELECT t.username
, t.theater_number
, t.movie_title
, i.key_exp
, i.key_exp_time
FROM movies_in_theater t
LEFT
JOIN movie_info i
ON i.title = t.movie_title
WHERE t.username = ?
AND t.theater_number = ?

Selecting data for 1 specific user from multiple tables

So my database is composed of 5 tables with different columns for each one. The only column that keeps them all identified is the id. I'm trying to get the data for a specific user, but I only seem to get all users of the database instead.
This is what I have tried:
SELECT
ControlAccess.UserName,
ControlAccess.Pass,
Users.First_Name,
Users.Last_Name,
UserInfo.Age,
UserInfo.Country,
UserInfo.Address,
UserInfo.ZipCode,
Sessions.Matrix1,
Sessions.Matrix2,
Sessions.Result,
Operations.Operation,
FilePath.LocationFiles
FROM
MatrixUsers.UserInfo
INNER JOIN
MatrixUsers.Users
ON
UserInfo.idUserInfo = Users.idUsers = 1
INNER JOIN
MatrixUsers.ControlAccess
ON
ControlAccess.idControlAccess = UserInfo.idUserInfo = 1
INNER JOIN
MatrixUsers.Sessions
ON
Sessions.idSessions = ControlAccess.idControlAccess = 1
INNER JOIN
MatrixUsers.FilePath
ON
FilePath.idFilePath = Sessions.idSessions = 1
INNER JOIN
MatrixUsers.Operations
ON
Operations.idOperations = FilePath.idFilePath = 1;
I tried putting 1 at the end of each id to see if they matched, but I still get all the users.
I'm new to SQL and I'm only familiar with matching rows, but not choosing specific one.
Here are the columns of each table:
ControlAccess: {idControlAccess, UserName, Pass}
Sessions: {idSessions, Matrix1, Matrix2, Result}
FilePath: {idFilePath, LocationFiles}
Operations: {idOperation, Operation}
UserInfo: {idUserInfo, Age, Country, Address, ZipCode, Phone}
Use WHERE when you want specific user. for example, select user_id from table where user_id=the_specific_user_id . Follow this basic to built you complicate statement.
Just user where after all the joins
WHERE ANY_COLUMN_REFER_TO_USER_ID = YOUR_NEEDED_ID
so your full query would be like :
SELECT
ControlAccess.UserName,
ControlAccess.Pass,
Users.First_Name,
Users.Last_Name,
UserInfo.Age,
UserInfo.Country,
UserInfo.Address,
UserInfo.ZipCode,
Sessions.Matrix1,
Sessions.Matrix2,
Sessions.Result,
Operations.Operation,
FilePath.LocationFiles
FROM MatrixUsers.UserInfo
INNER JOIN MatrixUsers.Users
ON UserInfo.idUserInfo = Users.idUsers
INNER JOIN MatrixUsers.ControlAccess
ON ControlAccess.idControlAccess = UserInfo.idUserInfo
INNER JOIN MatrixUsers.Sessions
ON Sessions.idSessions = ControlAccess.idControlAccess
INNER JOIN MatrixUsers.FilePath
ON FilePath.idFilePath = Sessions.idSessions
INNER JOIN MatrixUsers.Operations
ON Operations.idOperations = FilePath.idFilePath
WHERE UserInfo.idUserInfo = 1

SQL - LEFT JOIN multiple conditions - priority

I have 2 tables with a structure similar with this:
table: user
fields: id, active_office_address_id (this can be 0)
table: user_address
fields: id, user_id, type (home, office)
A user can have a "home" address (not mandatory) and multiple "office" addresses. I have a join to get a user address, but I want that if the user have a "home" address to get that address, not "office" address.
So, how can I get "home" address if exists, and only if that not exists to get "office" address. (In reality the query is much more complicated and the join is done on 4-5 tables)
SELECT * FROM user LEFT JOIN user_address ON (user.id = address.user_id AND
(user_address.type = "home" OR user.active_office_address_id = user_address.id))
group by user.id
You can use COALESCE() and join to your address table twice:
SELECT user.id
,COALESCE(home.address, office.address) AS Address
FROM user
LEFT JOIN user_address AS home
ON user.id = home.user_id
AND home.type = "home"
LEFT JOIN user_address AS office
ON user.active_office_address_id = office.user_id
GROUP BY user.id
Two left joins and a case statement will give you the address id you want.
SELECT user.*,CASE WHEN home_addr.id IS NOT NULL THEN home_addr.id ELSE ofc_addr.id END AS addr_id
FROM user
LEFT JOIN user_address AS home_addr
ON (user.id = home_addr.user_id AND home_addr.type = 'home')
LEFT JOIN user_address AS ofc_addr
ON (user.active_office_address_id = ofc_addr.id)
You could feed this back in as a sub-select for a particular user:
SELECT * FROM user LEFT JOIN user_address
WHERE user.id = ?
AND user_address.user_id = user.id
AND user_address.id IN
(SELECT CASE WHEN home_addr.id IS NOT NULL THEN home_addr.id ELSE ofc_addr.id END AS addr_id
FROM user
LEFT JOIN user_address AS home_addr
ON (user.id = home_addr.user_id AND home_addr.type = 'home')
LEFT JOIN user_address AS ofc_addr
ON (user.active_office_address_id = ofc_addr.id)
WHERE user.id = ?)
This assumes that only one home address exists per user.
At least in SQL Server, not sure about MySql, you can use a case statement in the order by clause, for example:
order by user.id, case user_address.type when 'home' then 1 else 2 end, --additional ordering clauses here

SQL join multiple times?

I am making a user status list of the following format "A like B's XXX". A and B are both registered users and have firstname and lastname and user id. How to join the status table with the user table twice to get the names of the two users? Thank you.
SELECT "SQACTION"."TIMECREATED",
"SQWORDLIST".*,
"SUBJECT"."FIRSTNAME" subject_fn,
"SUBJECT"."LASTNAME" subject_ln,
author.firstname author_fn,
author.lastname author_ln
FROM "SQACTION"
INNER JOIN "SQWORDLIST"
ON SQACTION.ACTION = SQWORDLIST.GUID
INNER JOIN "SQUSER" SUBJECT
ON SQACTION.SUBJECT = SUBJECT.GUID
LEFT JOIN SQDOCUMENT
ON SQACTION.ENTITY = SQDOCUMENT.GUID
LEFT JOIN SQUSER AUTHOR
ON SQDOCUMENT.AUTHORID = AUTHOR.GUID
WHERE (SUBJECT.GUID = 'B4D3BF632C0C4DB3AB01C8B284069D8F')
OR (SUBJECT.GUID IN ('67882AF3FA3C4254AF9A12CA0B0AB6E4',
'6A4B52FE233444838AACFE2AFFE4D38F',
'8CA3FB9061FF4710B51F1E398D3D1917'))
ORDER BY "TIMECREATED" DESC
This is what I have tried. Thank you.
You need to include the table name twice in the FROM clause, and use an alias so you can specify which fields from each instance of the table are used in the ON statement. You didn't provide enough details in your question to give an exact example, so here is something more general.
UserTable, with ID & Name
RegTable, with UserID, and SponsorID
select ut1.name as [User],
ut2.name as [Sponsor]
from UserTable ut1
inner join RegTable rt on ut1.id = rt.userid
inner join UserTable ut2 on rt.sponsorid = ut2.id
do you mean something like, status have two field links to user table?
select user_a.first_name as user_a_first_name, user_b.first_name as user_b_first_name, status.status_name
from status
left join users as user_a on user_a.id = status.user_from_id
left join users as user_b on user_b.id = status.user_to_id

mysql conditional join depends on a column

I'm trying to implement a generic notification system.. I have a data structure like this;
notification_base:id,type,object
notificiation_sub:id,user_id,not_base_id,lastNotifyTime
notification_action:id,user_id,not_base_id,action,creationDate
So basic scenario is, user create a notification base item by post a status, or upload a photo and etc.(ın this case status,photo refers to type field in notification_base table and object_id is post_id or photo_id depends on type)
Then user subscribe for this notification_base item..(user 3 subscribe notification_base 5 and last notify time x)
After that another user touch this notification_base item. (for example commenting a status or like a photo)
This action is recorded in notification_action table (user 5 make action 'like' on 12/02/2011)..
What I want is fetch the notification_base items from user subscription if last notifiytime smaller than a notification action then join them with notification_action..
I can succeed it with this sql ;
For user id 3;
select * from notification_action
inner join notification_base on notification_action.not_base_id = notification_base.id
inner join notification_sub on notification_action.not_base_id = notification_sub.not_base_id
where notification_sub.user_id = 3 and notification_sub.lastShowDate < notification_action.creationDate ;
result is almost what i want, for example
user x did 'action' on your object which has 'type' and object_id at time t
but I also want to join on object_id depends on type.. So I can actually learn which object touched.. But as you can see type is dynamic, if type = post object id refers post_id on post table, if type=photo object id refers photo_id on photo table and etc..
I try to do it something like this but got some syntax error;
SELECT *
FROM notification_action
INNER JOIN notification_base
ON notification_action.not_base_id = notification_base.id
INNER JOIN notification_sub
ON notification_action.not_base_id = notification_sub.not_base_id CASE notification_base.type
WHEN 'photo'
THEN (
INNER JOIN photo
ON photo.id = notification_base.object_id
)
ELSE (
INNER JOIN post
ON post.id = notification_base.object_id
)
END
WHERE notification_sub.user_id = 3
AND notification_sub.lastShowDate < notification_action.creationDate;
I know that it's not correct, it's like pseudo code
you can't conditionally create joins across tables. The best way to do is to use LEFT JOIN and use you CASE in your SELECT statement. You must have specify common columns you want to show,
SELECT *,
(CASE notification_base.type
WHEN 'photo'
THEN photo.columnName1
ELSE post.ColumnName1
END) as ColumnName1,
(CASE notification_base.type
WHEN 'photo'
THEN photo.columnName2
ELSE post.ColumnName2
END) as ColumnName2
FROM notification_action
INNER JOIN notification_base
ON notification_action.not_base_id = notification_base.id
INNER JOIN notification_sub
ON notification_action.not_base_id = notification_sub.not_base_id
INNER JOIN photo
ON photo.id = notification_base.object_id
INNER JOIN post
ON post.id = notification_base.object_id
WHERE notification_sub.user_id = 3
AND notification_sub.lastShowDate < notification_action.creationDate;