MySQL search with relations - mysql

I have 3 tables.
user
id
firstname
lastname
...
user_rel_domain
user_id
domain_id
value
domain
id
name
I would like to make a search that would match the firstname, the lastname and the domain(s) name(s) if the value in user_rel_domain is higher then 0.
How could I do this in a single MySQL query?
EDIT:
Ok, I though that this idea would be easy to integrate from the 3 tables example, but I actually have 6 tables and I don't think that the answers can be used for the structure I really have, so here it is, sorry everyone!:
user
id
firstname
lastname
...
user_rel_domain
user_id
domain_id
value
domain
id
name
user_rel_mandate
user_id
mandate_id
value
mandate
id
cat_id
name
mandate_cat
id
name
Basically I want to search in all the "name" columns and the firstname and lastname of the user table while all the value from the relation tables be higher then 0.

EDIT: Hmm... I made a few assumptions about your new requirements, so let me know if this is in the ballpark:
SELECT
u.firstName,
u.lastName,
d.name AS domainName,
m.name AS mandateName,
mc.name AS mandateCatName
FROM
user u
JOIN user_rel_domain urd ON urd.user_id = u.id AND urd.value > 0
JOIN domain d ON d.id = urd.domain_id
JOIN user_rel_mandate urm ON urm.user_id = u.id AND urm.value > 0
JOIN mandate m ON m.id = urm.mandate_id
JOIN mandate_cat mc ON mc.id = m.cat_id
WHERE
u.firstName = #SearchTerm
OR u.lastName = #SearchTerm
OR d.Name = #SearchTerm
OR m.Name = #SearchTerm
OR mc.Name = #SearchTerm

SELECT u.firstname, u.lastname, d.name
FROM user_rel_domain urd
INNER JOIN user u
ON urd.user_id = u.id
INNER JOIN domain d
ON urd.domain_id = d.id
WHERE urd.value > 0;

SELECT user.firstname, user.lastname FROM user
JOIN user_rel_domain ON user.id=user_rel_domain.user_id
JOIN domain ON domain.id=user_rel_domain.domain_id
WHERE user_rel_domain.value>0
edit: are you looking for an exact match eg name in all of the columns should be equal to string you are looking for? or is it enough if any of the names is equal?
maybe this then:
SELECT user.firstname, user.lastname FROM user
JOIN user_rel_domain ON user.id=user_rel_domain.user_id
JOIN domain ON domain.id=user_rel_domain.domain_id
JOIN user_rel_mandate ON user.id=user_rel_mandate.user_id
JOIN mandate ON user_rel_mandate.mandate_id=mandate.id
JOIN mandate_cat ON mandate.id=mandate_cat.mandate_ID
WHERE
user_rel_domain.value>0 AND
(user.firstname="string" OR user.lastname="string" OR domain.name="string" OR mandate.name="string")

Related

MySQL complex select query filtering from third table

I have three tables.
users, friends and communityusers tables.
I am trying to build a facebook like group system. User will try to search his/her friends from friend lists to add them to the group.
So here I am trying to remove those friends who are already added in the group. Here group users table is communityusers..
This is the structure of my communityusers table.
id | community_id | user_id
I am not being able to use this table with my current query.
SELECT f.id, u.id as user_id, u.userName, u.firstName, u.lastName, u.profilePic from friends f, users u
WHERE CASE
WHEN f.following_id=1
THEN f.follower_id = u.id
WHEN f.follower_id=1
THEN f.following_id = u.id
END
AND
f.status= 2
AND
(
u.firstName LIKE 's%' OR u.lastName LIKE 's%'
)
This query returns the friends lists of user id 1 now I want exclude users filtering from the communityusers table.
user_id from this query shouldn't be present in the communityusers table. How can I filter this from communityusers or third table?
Please let me know if question is not clear.
Any suggestion, idea and help would be highly appreciated.
Thank you so much.
Edit
After running the query I get
My communityusers table
See user_id = 2 is also selected from the above query. I want to remove the user_id = 2 from the result since it exists in the communityusers table.
I am trying to create a Fiddle but for some reason it's not working for me.
Thank you again.
#sadek
Simply use not in, in where condition
SELECT f.id, u.id as user_id, u.userName, u.firstName, u.lastName, u.profilePic
from friends f inner join users u on
CASE WHEN f.following_id=1 THEN f.follower_id = u.id WHEN f.follower_id=1 THEN f.following_id = u.id
END AND f.status= 2
where u.id not in (select distinct user_id from communityusers) and (u.firstName LIKE 's%' OR u.lastName LIKE 's%')
Try using left join with communityuser table by given condition cu.user_id is null - this will give you those users which are not in communituuser table
select a.* from
(SELECT f.id, u.id as user_id, u.userName, u.firstName, u.lastName, u.profilePic from friends f inner join users u
on CASE WHEN f.following_id=1 THEN f.follower_id = u.id WHEN f.follower_id=1 THEN f.following_id = u.id
END AND f.status= 2 where u.firstName LIKE 's%' OR u.lastName LIKE 's%')a
left join (select * from communityuser where community_id<>4) cu on a.user_id=cu.user_id
where cu.user_id is null

Join to a table that its name is in a row result

I have tables called comment, admin, user.
comment:
body userType userId
--------------------------------------------
comment1 admin 1
comment2 user 2
admin:
id title
-----------------------
1 amir
2 farhad
user:
id title
-----------------------
1 kazem
2 ali
I want to get the comment and userTypes' title from it's table by one query like:
SELECT u.title, c.body FROM comment c, c.userType u
but it doesn't work!
A couple options come to mind:
using a union:
SELECT title, body FROM comment c JOIN user u on c.userId = u.id and userType = 'user'
UNION
SELECT title, body FROM comment c JOIN admin u on c.userId = u.id and userType = 'admin'
using left joins:
SELECT
COALESCE(u.title, a.title) as title,
c.body
FROM comment c
LEFT JOIN user u on c.userId = u.id and userType = 'user'
LEFT JOIN user a on a.userId = u.id and userType = 'admin'
WHERE COALESCE(u.title, a.title) is not null;
This uses ANSI SQL COALESCE. If you are using T-SQL (MS SQL), you will need to use ISNULL instead.
More generically, this is a case of the "Concrete Table Inheritance" pattern, and the userType column is called a discriminator.

How can I extract the required data from these three tables using mysql?

Sorry but I'm struggling to work out the correct SQL to extract the required data from these three tables...
users:- id, firstname, lastname, email, live
contracts:- id, userid, contractid
userstage:- id, userid, stageid, statusid
I need firstname, lastname, email, live, from users
and contractid from contracts,
and statusid from userstage
WHERE users.live =1 AND contracts.contractid = 1 AND userstage.statusid <>4 (not equal to 4)
Thank you.
It's pretty basic SQL. Don't really see what your problem is. You might want to change to OUTER JOIN (left or right) depending on what you need.
SELECT u.firstname, u.lastname, u.email, u.live, c.contractid, us.statusid
FROM users AS u
INNER JOIN contracts AS c ON u.id = c.userid
INNER JOIN userstage AS us ON u.id = us.userid
WHERE u.live = 1 AND c.contractid = 1 AND us.statusid <> 4
Depending on what you want to do when some of the users have no contracts etc, you can start with:
SELECT firstname, lastname, email, live, contractid, statusid
FROM users
JOIN contracts ON contracts.userid = users.id
JOIN userstage ON userstage.userid = users.id
WHERE users.live =1 AND contracts.contractid = 1 AND userstage.statusid <>4 (not equal to 4)

GROUP_CONCAT() like function to return fields that don't match?

I have three tables in my database, for the purposes of discussion let's say they are:
USERS
-----
user_id
user_name
ROLES
-----
role_id
role
USER_ROLES
----------
user_role_id
user_id
role_id
I can easily use GROUP_CONCAT() to return a comma separated list of roles the user does have like so:
SELECT u.user_id, u.user_name, GROUP_CONCAT(role) AS roles_held
FROM users u,
roles r,
user_roles ur
WHERE u.user_id = ur.user_id
AND r.role_id = ur.role_id
GROUP BY u.user_id, u.user_name;
What I'd like to do is also return a list of roles the user does not have.
My initial thought was using sub-query then concatenating that, but I can't seem to get that to work. Can someone point me in the right direction?
Thank you!
EDIT: To clarify, the desired output would be a query that returns the user_id, user_name, a concatenated string of the roles the user does have and a concatenated string of the roles the user does not have. So for example:
USER_ID USER_NAME ROLES_HELD ROLES_LACKED
1 Bob User,Writer Editor,Admin
2 Doug User Writer,Editor,Admin
I agree with using a CROSS JOIN here, but it doesn't need to be quite so complicated:
SELECT
u.user_id,
u.user_name,
GROUP_CONCAT(case when ur.user_id is not null then r.role end) AS roles_held,
GROUP_CONCAT(case when ur.user_id is null then r.role end) as roles_lacked
FROM
users u
CROSS JOIN roles r
LEFT JOIN user_roles ur ON
u.user_id = ur.user_id
AND r.role_id = ur.role_id
GROUP BY
u.user_id, u.user_name
You could try to join table role two times The first time to get held roles, the second time to get lacked roles.
SELECT u.user_id,
user_name,
GROUP_CONCAT(DISTINCT r.role) AS role_held,
GROUP_CONCAT(DISTINCT r1.role) AS role_lacked
FROM users u
INNER JOIN user_roles ur
ON u.user_id = ur.user_id
INNER JOIN roles r
ON r.role_id = ur.role_id
INNER JOIN roles r1
ON NOT EXISTS (SELECT 1
FROM user_roles ur1
WHERE user_id = u.user_id
AND role_id = r1.role_id)
GROUP BY u.user_id,
user_name
I've created a demo here

SQL - Join two tables

I have two tables
Users: (id, name)
Relations: (user_id, relation_id)
User_id and relation_id are both ids from the table users.
What I want is ro recover all users who are friend with a specific user.
And here is my sql command: that doesn't work:
SELECT *
FROM users
NATURAL JOIN relations
WHERE user_id IN (SELECT id FROM users WHERE name='John doe');
Could you help me?
SELECT users.*
FROM relations
INNER JOIN users
ON relations.relation_id = users.id
WHERE relations.user_id = 12345;
You can also get the id with a subquery, just as you did in your example:
WHERE relations.user_id IN (SELECT id FROM users WHERE name='John doe');
To get all the relations a person has , the following query will work..
SELECT * FROM users us JOIN relations re ON us.id = re.relation_id
WHERE re.user_id = (
SELECT id
FROM users
WHERE name = 'John doe'
)
Try this
SELECT * FROM users as a
JOIN relations as b on a.id = b.user_id
WHERE b.user_id IN (SELECT id FROM users WHERE name='John doe')
SELECT user_id
FROM relations re
JOIN users us
ON us.id = re.user_id
WHERE relation_id = (
SELECT id
FROM users
WHERE name = 'John Doe'
)
Side note: you can't use NATURAL JOIN here, 'cause there is no column that have the same name and type in the two tables.
isnt this just a matter of querying the relations tables by the userId you are looking for?
select *
from relations
where user_id = #IdYouArelookingFor or relation_id = #IdYouArelookingFor
SELECT friend.*
FROM users AS friend
JOIN relations AS r
ON r.relation_id = friend.id
JOIN users AS u
ON u.id = r.user_id
WHERE u.name = 'John doe' ;
Friends are people with the same relation_id?
SELECT a.name FROM users a JOIN relations b on a.id = b.user_id
WHERE b.relation_id in
(select relation_id from relations where id = 'userid of user you are looking for')
AND a.id != 'userid of user you are looking for'
If your logic is different pls tell how it is working