Or condition in INNER JOIN - php

I have a table structured as follows (points):
id1 | id2 | p1 | p2
1 3 5 7
3 1 2 4
1 2 1 7
And another table strucuted as follows (users):
id | name
1 User1
2 User2
3 User3
So now, I need a query that specifing an ID (for example 3), the query check that the ID appears in the column id1 and id2, and if it appears in one of the two columns, it gives me back the user name with id1 and id2 from the rows selected. So, for example if I specific the ID 3, the query give me back:
name1 | name2 | p1 | p2
User1 User3 5 7
User3 User1 2 4
I tried various solutions but no way to do it, I think that I need an OR condition in the INNER JOIN but I don't know if it's possible and if it's the solution.. I didn't find nothing here.
I mean something like:
INNER JOIN users ON (users.id = points.id1) || (users.id = points.id2)
Any solution for that? Thanks

Join the user table twice:
SELECT u1.name, u2.name, p.p1, p.p2
FROM points p
JOIN users u1 ON u1.id = p.id1
JOIN users u2 ON u2.id = p.id2
WHERE u1.id = 3 OR u2.id = 3

Use case statement it will give you all matching value not need restricted for one or two values
CREATE TABLE points (id1 int(2), id2 int(2), p1 int(2), p2 int(2));
INSERT INTO points VALUES(1,3,5,7);
INSERT INTO points VALUES(3,1,2,4);
INSERT INTO points VALUES(1,2,1,7);
CREATE TABLE users (id int(2), name char(23));
INSERT INTO users VALUES(1,'user1');
INSERT INTO users VALUES(2,'user2');
INSERT INTO users VALUES(3,'user3');
SELECT (CASE WHEN u.id = p.id1 THEN u.name END) AS name1,
(CASE WHEN u1.id = p.id2 THEN u1.name END) AS name2,
p1, p2
FROM points p
INNER JOIN users u ON (u.id = p.id1)
INNER JOIN users u1 ON (u1.id = p.id2);

Related

Join with condition with different column

I have following two tables :
user_profile
id | name | email | phone
1 | Rahul |r#gmail.com |1234567890
2 | Rohan |r1#gmail.com |1234567890
3 | Mohan |m#gmail.com |1234567890
user_request_table
id | from_user_id|to_user_id|status
1 | 1 | 2 | 2
2 | 3 | 1 | 2
Here status
0 = Request is cancel,
1 = request is pending,
2 = request accepted
I have following section to display :
Find a friend
Here I need to display suggetion for friend. I need to display all record from user_profile table but user should not be a friend(status should not be 2) or request should not be pending(status should not be 1).
So if I logged in as Rohan(id : 2) it should suggest me Mohan as friend suggestion.
Would this work:
SELECT
u.*
FROM
user_profile u
LEFT JOIN user_request_table r ON u.id=r.to_user_id AND r.from_user_id = <your_logged_in_user_id>
WHERE
r.status NOT IN (2,1) --filter pending and accepted here ;
So you want those records in user_profile table that do not have a record in user_request table where user is either from_user_id or to_user_id. The pattern is to do a left join to user_request and filter out those where user_request.id is null:
select
p.*
from
user_profile as p
left join user_request as r on
(
(p.id = r.from_user_id and r.to_user_id = {id})
or
(p.id = r.to_user_id and r.from_user_id = {id})
)
and r.status in (1,2)
where
r.id is null
and p.id <> {id}
;
with {id} a parameter for the user you want to suggest friends for.
First get all possible pairs from the user_profile table. Next filter through all the pairs and eliminate the unqualified using data from the user_request_table. It will get all the eligible (from_user , to_user)pairs.
select u1_id as fromuser,u2_id as touser
from
(select distinct u1.id as u1_id,u2.id as u2_id from user_profile u1 cross join user_profile u2 where u1.id!=u2.id) all_pair
where not exists
(select from_user_id ,to_user_id from user_request_table where status>0 and (
((u1_id=from_user_id) and(u2_id=to_user_id)) or ((u1_id=to_user_id) and(u2_id=from_user_id))
)
)
;
The result set looks like this:
fromuser, touser
3 2
2 3
This solution is for MSSQL SERVER, you can modify as per your preferred server
Pass your logged in id to declared variable
DECLARE #LoginId AS INT
SET #LoginId=2 /*here I passed logged in id as 2*/
SELECT * FROM user_profile up
WHERE 1=1 and id<>#LoginId
AND id NOT IN (SELECT from_user_id FROM user_request_table WHERE to_user_id=#LoginId and STATUS in(1,2))
AND id NOT IN (SELECT to_user_id FROM user_request_table WHERE from_user_id=#LoginId and STATUS in(1,2))

Need help MySQL query. Need data from two tables

I am a beginner in MySQL.
Table 1: Users
ID NAME
----------
1 XYZ
2 ABC
Table 2: Task
ID TASK_NAME ASSIGNED_BY ASSIGNED_TO
--------------------------------------------
1 task 1 1 2
2 task 2 2 1
I want this result.
ID TASK_NAME ASSIGNED_BY ASSIGNED_TO
--------------------------------------------
1 task 1 XYZ ABC
2 task 2 ABC XYZ
Its a simple JOIN task:
SELECT t.ID, t.TASK_NAME,
u1.NAME AS ASSIGNED_BY,
u2.NAME AS ASSIGNED_TO
FROM Task AS t
JOIN Users AS u1 ON t.ASSIGNED_BY = u1.ID
JOIN Users AS u2 ON t.ASSIGNED_TO = u2.ID
You need to use JOIN to do it. I use INNER JOIN please try the following query.
SELECT t.ID, t.TASK_NAME,
u1.NAME AS ASSIGNED_BY,
u2.NAME AS ASSIGNED_TO
FROM Task AS t
INNER JOIN Users AS u1 ON t.ASSIGNED_BY = u1.ID
INNER JOIN Users AS u2 ON t.ASSIGNED_TO = u2.ID

How to join tables based on the column value in a table

I have the table news_feed in which all of my different types of activities data will be stored like admin activities, user activities, company activities etc. The table format looks like:
news_id | type | admin_id | user_id | company_id
1 | admin | 2 | 3 | 0
2 | user | 3 | 4 | 1
3 | company | 0 | 1 | 2
Suppose a user with an id 1 has liked the company which has id 2 then the record will be inserted like
4 user 0 1 2
And I'm listing them in my module and the listing is perfect. But suppose if the company id 2 doesn't exist or if it is inactive, then the news_feed block in listing getting empty. What I want to do is:
If the type is company then JOIN the company table while select listing with condition for status as active
If the type is user then JOIN the user table while select listing with condition for status as active
Well you can use UNION for this issue
SELECT t.column1, t.column2, t.column3
FROM my_table t INNER JOIN company_table c
ON t.company_id = c.id
WHERE c.active=1 AND t.type = "company"
UNION
SELECT column1, column2, column3
FROM my_table t INNER JOIN user_table u
ON t.user_id = u.id
WHERE c.active=1 AND t.type = "user"
Just to add, to increase the efiiciency use UNION ALL rather than UNION (or UNION DISTINCT) as UNION requires internal temporary table with index (to skip duplicate rows) while UNION ALL will create table without such index, but keep in mind it will skip the repeated data.
But more optimized way to do a Conditional Join in MySQL by using a INNER JOIN
SELECT t.column1, t.column2, t.column3
FROM my_table t
INNER JOIN company_table c
ON (t.company_id = c.id AND t.type = "company" AND c.active=1)
INNER JOIN user_table u
ON (t.user_id = u.id AND t.type = "user" AND u.active=1);

MySQL: Get all users not a part of a group

I'm trying to get my head around this query but one of the records still keeps popping up. In summary, my intention is to show group members on the left and names from a phonebook which are not included in the group on the right. That way the user can select them and add them to the group.
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
3 Sam 2 Awesome Group
4 Mitch 1 Some Group
4 Mitch 2 Awesome Group
5 Rocky (NULL) (NULL)
6 Pops (NULL) (NULL)
The unique thing is that if one of the users is a part of multiple groups (user_id 4), their name should not be shown in the phonebook at all since it would already be placed in the list of existing members.
-- Query for group_id 2
SELECT user.id user_id, user.firstname, grp.id group_id, grp.grpname FROM agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
WHERE grp.id IS NULL OR grp.id != 2
GROUP BY user.id
but for some reason the user Mitch still keeps popping up.
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
4 Mitch 1 Some Group
5 Rocky (NULL) (NULL)
6 Paps (NULL) (NULL)
Edit:: The output I need is
user_id firstname group_id grpname
------- --------- -------- ----------
1 Luker 3 Abc
2 John 1 Some Group
5 Rocky (NULL) (NULL)
6 Paps (NULL) (NULL)
Basically, to I want to get all users not a part of that group including NULL. But since one user is a part of multiple groups, her record still comes up when it shouldn't because that other group probably has a group_id of 3 or 4 (or any other besides 2).
You can use NOT EXIST to check if there are no group/user rows at all for group 2 and the given user:
SELECT
user.id user_id,
user.firstname,
grp.id group_id,
grp.grpname
FROM
agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
WHERE
NOT EXISTS (
SELECT 'x' FROM agi_group_user x
WHERE
x.user_id = user.user_id and
x.group_id = 2)
GROUP BY
user.id
Note that if a user is not in group 2, but is in two other groups, he will show up 1 time in this result and only one of the groups he is in is returned. To fix that, you can add grp.id to the GROUP BY clause, or maybe you can use GROUP_CONCAT to return a list of group names in a single field.
Alternatively, this should work too, and in MySQL it might even perform better since it sucks at subqueries. Personally I think it is semantically less clear what is going on, though.
It joins the user/groups table a second time, but adds the group_id (2) to the join. If there are no rows returned for this table, then the user is not in group 2. The comment regarding GROUP_CONCAT applies to this query as well.
SELECT
user.id user_id,
user.firstname,
grp.id group_id,
grp.grpname
FROM
agi_user user
LEFT JOIN agi_group_user gu ON user.id = gu.user_id
LEFT JOIN agi_groups grp ON gu.group_id = grp.id
LEFT JOIN agi_group_user x ON user.id = x.user_id and x.group_id = 2
WHERE
x.group_id IS NULL
GROUP BY
user.id
If I understood correctly, you want this: "All users that are not in group 2"
This is called an anti-semijoin (or just anti-join) and can be done with a LEFT JOIN /IS NULL query:
SELECT u.id user_id, u.firstname
FROM agi_user AS u
LEFT JOIN agi_group_user AS gu
ON u.id = gu.user_id
AND gu.group_id = 2
WHERE gu.group_id IS NULL ;
or with a NOT EXISTS subquery:
SELECT u.id user_id, u.firstname
FROM agi_user AS u
WHERE NOT EXISTS
( SELECT 1
FROM JOIN agi_group_user AS gu
WHERE u.id = gu.user_id
AND gu.group_id = 2
) ;

MySQL require multiple values from multiple rows of a join

I have the following table structures.
Table A
id name
1 name1
2 name2
Table B
a_id b_id
1 1
1 2
How can I select all rows of table A that have both a b_id of 1 and 2? Table B is a mapping table between table A and another table, whose contents do not matter for this question.
Thank you for your time and help!
This query uses COUNT(DISTINCT) to ensure the presence of both values. If I did not use DISTINCT it may incorrectly count rows in TableB that look like this as a match when it shouldn't:
a_id b_id
1 1
1 1
select a.id, a.name
from TableA a
inner join (
select a_id
from TableB
where b_id in (1, 2)
group by a_id
having count(distinct b_id) = 2 #this number matches no. of unique values in IN clause
) b on a.id = b.a_id
SQL Fiddle example
Correctness can be tricky on a question like this because your sample data is missing a key cases. Duplicate values for B_ID and the possibility that it can contain one of the ids but not both
e.g.
| A_ID | B_ID |
---------------
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 1 |
The best approach is to use Having (Distinct Count) = # of ids (RedFilter's) since its easy to add more ID's
The two other options are to use or multiple EXISTS or IN clauses (NickB's) or to join and filter multiple times (below) but can become tortuously long if you need to add additional ids.
SELECT DISTINCT a.id,
a.name
FROM TableA a
INNER JOIN TableB b1
ON a.id = b1.a_id
and b1.b_id = 1
INNER JOIN TableB b2
ON a.id = b2.a_id
and b2.b_id = 2
DEMO
SELECT * FROM A JOIN B ON A.id=B.a_id WHERE B.b_id IN(1,2);
Here's what I could come up with, it uses one subquery.
SELECT * FROM table_a a1
JOIN table_b b1
ON a1.id = b1.a_id
WHERE b1.b_id = 1 AND
EXISTS(
SELECT b2.b_id
FROM table_b b2
WHERE a1.id = b2.a_id
AND b2.b_id = 2
)
Didn't know SQL Fiddle exists, but here is one showing it working!
I'll take a stab at this too, with a self join:
SELECT A.* FROM B B1
JOIN B B2 ON B2.a_id = B1.a_id
JOIN A ON A.id = B1.a_id
WHERE B1.b_id = 1 AND B2.b_id = 2
I tested this, and it works. If (B.a_id, B.b_id) isn't unique, then you'll need DISTINCT to avoid duplicates.
SELECT TableA.* FROM TableA WHERE TableA.id IN(
SELECT TableB.a_id FROM TableB WHERE TableB.b_id IN(1,2))

Categories