mysql joins on multiple table depending on the value of column - mysql

I am using a post table and two type of entities school and user can add something to this table. post table has a post_from field to differentiate whether post is from user or school.
i want to write one query with join to user table or school table depending on post_from field.
SELECT *
FROM post
LEFT JOIN `user`
ON (user.id = post.uid AND post.post_type = 'user' )
LEFT JOIN school_profile
ON (school_profile.id = post.school_id AND post.post_type = 'school')

You can do this with a union :
SELECT post.*
FROM post
INNER RJOIN `user`
ON (user.id = post.uid AND post.post_type = 'user' )
union
SELECT post.*
FROM post
INNER JOIN school_profile
ON (school_profile.id = post.school_id AND post.post_type = 'school')
Alternatively, you can do this :
SELECT *
FROM post
LEFT JOIN `user` ON (user.id = post.uid)
LEFT JOIN school_profile ON (school_profile.id = post.school_id)
WHERE post.post_type IN ('user', 'shcool')

Related

Filtering on joins with two foreign keys

Say I have two tables, users and addresses (contains columns id and text). I have two address columns in users, say temp_address_id and permanent_address_id.
If I want to get add the users with temp_address = 'SF' or permanent_address = 'MTV', is the following query the only way out?
SELECT * FROM users
JOIN addresses ON (
(users.temp_address_id = addresses.id AND addresses.text = 'SF')
OR (users.permanent_address_id = addresses.id AND addresses.text = 'MTV')
)
I don't think there is a way to specify the filters (addresses.text = 'SF' and addresses.text = 'MTV') in the WHERE clause. Is that right?
If you want only the users, I would recommend two exists:
SELECT u.*
FROM users u
WHERE EXISTS (SELECT 1
FROM addresses a
WHERE u.temp_address_id = a.id AND a.text = 'SF'
) OR
EXISTS (SELECT 1
FROM addresses a
WHERE u.permanent_address_id = a.id AND a.text = 'MTV'
);
This should have much better performance than OR in the JOIN clause, especially with an index on addresses(id, text).
If you need address information returned, use two left joins:
SELECT u.*, COALECE(ta.text, tp.text) as text
FROM users u LEFT JOIN
addresses ta
ON u.temp_address_id = ta.id AND
ta.text = 'SF' LEFT JOIN
addresses tp
ON u.permanent_address_id = ta.id AND
ta.text = 'MTV'
WHERE ta.id IS NOT NULL OR tp.id IS NOT NULL;
The downside to this approach is that you need to use COALESCE() for each of the columns selected from the address table.
Edit: Changed join condition to include both addresses.
Why can't you do following? Have you tried it?
SELECT u.*,COALESCE(a.text,b.text) AS text
FROM users u
LEFT JOIN addresses a ON u.temp_address_id = a.id AND a.text = 'SF'
LEFT JOIN addresses b ON u.permanent_address_id = b.id AND b.text = 'MTV';

SQL Data Duplication

sql query
SELECT `user`.`email`,
`user`.`passwrd`,
`user`.`status`,
`useraccounts`.`Balance`,
`useraccounts`.`AccountID`, `accounts`.`AccountNo`,
wallet.Server_typ,wallet.DateBought,
wallet.LastDate,
wallet.Profit,
withdraws.walletAdrs,
withdraws.Amount,
withdraws.status AS WDStatus,
withdraws.message,
withdraws.Date
FROM `user`
LEFT JOIN `useraccounts` ON `user`.`email` = `useraccounts`.`email`
LEFT JOIN `accounts` ON `accounts`.`AccountID` = `useraccounts`.`AccountID`
LEFT JOIN wallet ON user.email = wallet.email
LEFT JOIN withdraws ON user.email = withdraws.email
WHERE user.type = 'user'
This is my query, it works fine but there are many records against an email address. Because of this, my email gets duplicate. whenever i call just email duplicate records come. I just want one email.thanks in advance
SELECT DISTINCT `user`.`email`, `user`.`passwrd`, `user`.`status`,`useraccounts`.`Balance`, `useraccounts`.`AccountID`, `accounts`.`AccountNo`,wallet.Server_typ,wallet.DateBought,wallet.LastDate,wallet.Profit,withdraws.walletAdrs,withdraws.Amount,withdraws.status AS WDStatus, withdraws.message, withdraws.Date
FROM `user`
LEFT JOIN `useraccounts` ON `user`.`email` = `useraccounts`.`email`
LEFT JOIN `accounts` ON `accounts`.`AccountID` = `useraccounts`.`AccountID`
LEFT JOIN wallet ON user.email = wallet.email
LEFT JOIN withdraws ON user.email = withdraws.email
WHERE user.type = 'user'
Using DISTINCT will provide only distinct records.

Duplicate column on join

I'm trying to join three tables, after filtering one down to the most recent entry per user. However, all of a sudden I'm running into the error Duplicate column name 'username'. I need to join on this "duplicate" column. How do I fix this?
SELECT customers.id,customers.name,customers.username,customers.phone,customers.email,radcheck.value as password
FROM customers
RIGHT JOIN radcheck ON customers.username = radcheck.username
LEFT JOIN (
SELECT * FROM radacct INNER JOIN (
SELECT username,MAX(acctupdatetime) AS latest FROM radacct GROUP BY username
) as radrecent
ON radacct.username = radrecent.username
AND radacct.acctupdatetime = radrecent.latest
) as radlatest
ON customers.username = radlatest.username
WHERE radcheck.attribute = 'Cleartext-Password'
In the * you have two columns that are username. You need to qualify one or both of them. Example below:
SELECT
customers.id,customers.name,customers.username,customers.phone,customers.email,radcheck.value as password
FROM customers
RIGHT JOIN radcheck ON customers.username = radcheck.username
LEFT JOIN (
SELECT radrecent.username, latest FROM radacct INNER JOIN (
--^^^^^^^^^
SELECT username,MAX(acctupdatetime) AS latest FROM radacct GROUP BY username
) as radrecent
ON radacct.username = radrecent.username
AND radacct.acctupdatetime = radrecent.latest
) as radlatest
ON customers.username = radlatest.username
WHERE radcheck.attribute = 'Cleartext-Password'

SQL query from multiple tables with multiple JOINs

I have the following database where user account details are stored in the Users table, organisation details are linked to users through the 'UsersOrganisation_Map' junction table and user permissions are linked to users through the UsersSiteRoles_Map junction table. The database is MySQL
What I'm struggling with is how to get data from both the roles and org tables in a single query and have the results returned as if they're from a single table.
Here's an example script (that doesn't work) that will hopefully describe what I'm trying to achieve.
> select * from UsersOrganisation_Map, UsersSiteRoles_Map join Users on
> UsersOrganisationMap.userID = Users.userID join Organisation on
> UsersOrganisationMap.organisationID = Organisation.organisationID
> where userEmail = 'admin#test.com' AND userPassword = 'test' AND
> accountActive = 'YES' join Users on UsersSiteRoles_Map.userID =
> Users.userID join SiteRoles on UsersSiteRoles_Map.roleID =
> SiteRoles.roleID
This should be something similar to:
SELECT
u.*,
usr.*,
sr.*,
uom.*,
o.*
FROM
Users as u
JOIN UsersSiteRoles_Map as usr
ON u.userID = usr.UserId
JOIN SiteRoles as sr
ON UsersSiteRoles_Map.roleID = sr.roleID
JOIN UsersOrganisation_Map as uom
ON u.userID = uom.userID
JOIN Organisation as o
ON o.organisationID = uom.Id
WHERE
u.userEmail = 'admin#test.com'
AND u.userPassword = 'test'
AND u.accountActive = 'YES'
You just need to join all the five tables together like :
SELECT *
FROM Users u
-- join to get roles
JOIN UsersSiteRoles_Map ur ON u.id=ur.user_id
JOIN SiteRoles r ON um.role_id=r.id
-- join to get organisation
JOIN UsersOrganisation_Map uo ON u.id=uo.user_id
JOIN Organisation o ON uo.organisation_id=o.id
-- filter results
WHERE u.email=admin ...

How to check a record belongs to user in MySQL?

I've a SQL Query:
SELECT r.*, t.title, t.active, ticket_author.username as ticket_author, responser.username, responser.isAdmin, responser.isMod
FROM `support_tickets_replies` r
LEFT JOIN `support_tickets` t ON (t.id = r.tid)
LEFT JOIN `users` ticket_author ON (ticket_author.id = t.uid)
LEFT JOIN `users` responser ON (responser.id = r.uid)
WHERE r.tid = [something goes here]
I must check, does that ticket belongs to current user. User ID is in t.uid. When it's not that user, just returns column "error" with message "Forbidden". It's possible to do with only MySQL?
SELECT r.*, t.title, t.active, ticket_author.username as ticket_author, responser.username, responser.isAdmin, responser.isMod
FROM `support_tickets_replies` r
LEFT JOIN `support_tickets` t ON (t.id = r.tid)
LEFT JOIN `users` ticket_author ON (ticket_author.id = t.uid)
LEFT JOIN `users` responser ON (responser.id = r.uid)
WHERE r.tid = [something goes here]
AND t.uid = [User ID goes here]
This query will only turn up records that belong to the user.
If the record doesn't belong to the user, it will return nothing.