Getting data from multiple mysql tables WHERE. - php

I have 2 database tables.
One called files. Which looks like this.
FILES
USERID FILENAME DEFAULT NETWORKID
88 hello 1 10293
9 bob
43 opener 1 10293
43 facepa
9 closer
Second table user networks
USERID NETWORKID
9 10293
43
My current sql query is
SELECT file,filename,filetype,size, forename, files.userID
FROM (`files`)
LEFT JOIN users ON users.userID = files.userID
WHERE files.userID = $userID ORDER BY id DESC
This currently gets the list of files where userid is 9.
As you can see my userid 9 is also in the usernetworks table and I am connected with network id 10293.
I want to also include in the query, any of the rows that default is 1 and the network id matches to any of those in the usernetworks table with my userID.
So where userid is connected to networkid, also show those results aswell as the ones with userid and no network id.
Any help appreciated.

If I read your logic correctly, then we can implement it by first left joining files to users on the condition that the user matches to your user ID. Then, we can left join again to users, this time on the condition that the file record is default, the network IDs match, and the matching user is also your user.
SELECT f.*
FROM files f
LEFT JOIN users u1
ON f.userID = u1.userID AND f.userID = $userID
LEFT JOIN usernetworks u2
ON f.default = 1 AND
f.networkid = u2.networkid AND u2.userID = $userID
WHERE
u1.userID IS NOT NULL OR u2.userID IS NOT NULL;
Actually, if you don't plan on selecting any columns from the users table then you can probably omit the join to that table completely. I have left it in as it is true to the original query in your question.

I understand you want your files plus the default files in your networks:
SELECT userid, filename, networkid
FROM files
WHERE (userid = $userid
OR (default = 1 AND networkid in (
select networkid from network_users where userid = $userid)))
AND filename like :name
Your SQL mentions fields that are not in your schema description.

If you want to get the data on the basis of network id than please use this query
SELECT file,filename,filetype,size, forename, files.userID
FROM files a, network b
WHERE a.networkID = b.networkID ORDER BY id DESC
.
Hope this will solve your problem

Related

How to check if a user follows another user from a list of users?

I'm creating a follow system in PHP where users can follow/unfollow other users. So far, when a user follows any other user, the id of both the users are stored in 'follow' table in MYSQL database,
u_id | f_id
===========
1 | 2
1 | 3
1 | 5
Where u_id follows f_id
Now when u_id 1 performs a search on the website, all the users with matching search query are presented, each having a button so that u_id 1 may follow them, but there may be some users that are already followed by u_id 1. How do I implement such that those users already followed by u_id 1 does not have that follow button?
One way is to check every result if they are followed by u_id 1 before presenting the search result, but I guess this will be very slow.
Is there any way so that I can do this in a single MYSQL query?
when u_id = 1 performs a search on the website, all the users with matching search query are presented
Looks like you have some kind of query returning user_id and a suggested user f_id to follow. Let assume that is a table suggestion
SELECT s.f_id,
CASE
WHEN f.id IS NULL THEN 'ON'
ELSE 'OFF'
END as ButtonStatus
FROM [suggestion] s
LEFT JOIN [follow] f
ON s.user_id = f.u_id
AND s.f_id = f.f_id
WHERE
s.user_id = #user_id // Variable from your UI.
$sql = "SELECT u.*, f.followingUsersId AS followingUsersId
FROM users AS u LEFT JOIN (SELECT followingUsersId FROM follow WHERE followerUsersId = '".$_SESSION['userid']."') AS f ON u.usersId = f.followingUsersId
WHERE u.usersName LIKE '%$searchvalue%' ORDER BY f.followingUsersId DESC, u.usersId DESC;";
Worked for me!!

Getting a Triple Join To Work When Rows Are Missing?

I have 3 tables. 1 table is like the master table and I want all rows from this table where GameID = X. Then I have a guides table which will have a matching ID and finally i have a user table that defines whether the user has selected this row to be hidden. this is causing issues. This table may not have a row associated with it. This table is shared amongst ALL users. The primary key of this table is UserID+InfoID. The query below returns what I want provided there are no other rows in the table for other userIDs.
SELECT PS_Info.*, PS_Guides.Guide, PS_Userhidden.* FROM PS_Info
LEFT JOIN PS_Guides ON PS_Info.ID = PS_Guides.InfoID
LEFT JOIN PS_Userhidden ON PS_Info.ID = PS_Userhidden.InfoID
WHERE PS_Info.GameID = :ID AND (PS_Userhidden.UserID = :UserID)
OR (PS_Userhidden.UserID IS NULL AND PS_Userhidden.InfoID IS NULL)
So I will run the php script and have infoID =1 and userID=1. In the table there is infoID=1 and userid = 2, but nothing will be returned for this row. If I remove PS_Userhidden.UserID = :UserID I get multiple of the same row. The user table will grow to millions of rows. I need a way to make this query stick to the primary key of the users table so it will still return a row if no match exists in the user table and also return a row if there is a match in the users table for the specific user
I think you just need to move the condition on the hidden user to the ON clause:
SELECT i.*, g.Guide, h.*
FROM PS_Info i LEFT JOIN
PS_Guides g
ON i.ID = g.InfoID LEFT JOIN
PS_Userhidden h
ON i.ID = h.InfoID AND h.UserID = :UserID
WHERE i.GameID = :ID ;
Your description of the problem sounds like something that can happen when you start fiddling with conditions in the WHERE clause of a LEFT JOIN. It is a little hard to follow though. If this doesn't work, edit your question with sample data and desired results -- or, better yet, set up a SQL Fiddle.

SQL Optimization WHERE vs JOIN

I am using mysql and this is a query that I quickly wrote, but I feel this can be optimized using JOINS. This is an example btw.
users table:
id user_name first_name last_name email password
1 bobyxl Bob Cox bob#gmail.com pass
player table
id role player_name user_id server_id racial_name
3 0 boby123 1 2 Klingon
1 1 example 2 2 Race
2 0 boby2 1 1 Klingon
SQL
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`,`users`
WHERE `users`.`id` = 1
and `users`.`id` = `player`.`user_id`
I know I can use a left join but what are the benefits
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
LEFT JOIN `users`
ON `users`.`id` = `player`.`user_id`
WHERE `users`.`id` = 1
What are the benefits, I get the same results ether way.
Your query has a JOIN in it. It is the same as writing:
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
INNER JOIN `users` ON `users`.`id` = `player`.`user_id`
WHERE `users`.`id` = 1
The only reason for you to use left join is if you want to get data from player table even when you don't have matches in users table.
LEFT JOIN will get data from the left table even if there's no equal data from the right side table.
I guess at one point, that player table's data will not be equivalent to users table specially if the data on users table has not been inserted into player table.
Your first query might return null on cases that the 2nd table (player) has no equivalent data corresponding to users table.
Also, IMHO, setting up another table for servers is a good idea in terms of complying to the normalization rules in database structure. After all, what details of the server_id is the column on player table pointing to.
The first solution makes a direct product (gets and connects everything with everything) then drops away the bad results. If you have a lot of rows this will be very slow!
The left join gets first the left table then put only the matching rows from the right (or null).
In your example you don't even need join. :)
This'll give you the same result and it'll be good until you just check for user id:
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
WHERE `player`.`user_id` = 1
Another solution if you want more conditions, without join could be something like this:
SELECT * FROM player WHERE player.user_id IN (SELECT id FROM user WHERE ...... )

Left/Inner join with AND,WHERE, and OR

I have 2 tables:
Friends
ID | Profile | Check
------+-----------+---------
int | int | bool
Where ID is person who sent original friend request, Profile is ID of person request was sent to, and Check is 0 = request pending; 1 = request accepted.
Messages
OwnerID | ...
-----------+-------
int | ...
Where OwnerID is ID of member who wrote the message.
So basically, what I am looking at is first:
select all rows from friends_list table where ID or Profile is equal to the memberID cookie. BUT heres my plight: If I send another user a friend request, then my ID is placed in the ID field and their ID is placed in the Profile field of the friend_list table. But if another user requests a friend request from me, then my ID would go into the Profile field and theirs would go in the ID field.
So, I would have a row where ID = 1, and Profile = 2. And the next row would be ID = 3 and Profile = 1. Now, both users with IDs 2 and 3 are friends of mine (ID 1), So I need to show all messages from 1, 2, and 3 (mine and my two friends) where check = 1
I think what you want is this:
(
SELECT m.*
FROM Messages m
INNER JOIN Friends f ON m.OwnerID = f.ID
WHERE f.Profile = ?
) UNION (
SELECT m.*
FROM Messages m
INNER JOIN Friends f ON m.OwnerID = f.Profile
WHERE f.ID = ?
)
You need to look at this a two separate queries, I don't think you can sensibly do this with just a combination of JOINs.
Assuming you are using MySQL, this should not return duplicate rows, because the default modifier for UNION is DISTINCT. Other RDBMS engines may require you to explicitly state this or use some other work-around (for example a GROUP BY on the actual message ID).
You may also want to add an m.Check = 1 condition to the WHERE clause of both queries, to ensure you only get messages where the friend request has been accepted.
Obviously the above is designed to be used as a prepared statement, where both placeholders would be substituted with the same data - the memberID cookie.

filtering sql search by two variables having same result

I'm not sure how I can do this but I have two tables:
--users--
id_users (index)
name_users
--friend--
id_friend (index)
id_user (connects to id_users)
linked_friend (also links to id_users as this is the id of the requested friend)
for a friendship to be requested one row exists with the user who requested in friend.id_user col and the user they are requesting being in the friend.linked_friend col. To confirm the friendship link another row is created with the info reversed so that there are two rows for each friendship with each user being in the friend.id_user AND the friend.linked_friend col. (let me know if I could do this in a better way)
so what I need to do is for each user list all users on the system that are in a confirmed friendship (two rows) and aren't themselves.
SELECT id_user, name_user FROM user WHERE id_user <> $userId
obviously removes themselves from the list but I'm at a loss as to how to select users that have both rows.
I hope that is clear enough.
Thanks
You could join the friend table twice to demand that rows in both direction exist:
select u1.name
, u2.name
from users u1
join friend f1
on u1.id_users = f1.id_user
join friend f2
on f2.id_user = f1.linked_friend
and f2.linked_friend = f1.id_user
join users u2
on u2.is_users = f2.id_user
and u1.id_users < u2.id_users -- Display friends once
I agree with Jack Pettinger that this design is fairly clunky. There should be only one row in the friends table for each relation. It should have a unique constraint to enforce that, like:
alter table Friends add constraint CHK_Friend check (friend1_id < friend2_id);
create index UX_Friends on Friends (friend1_id, friend2_id);
you have to use Join if you want to fetch data from two or more tables.
Try this
select * from users left join friend on users.id_users = friend.id_user
// you also give where condition for particular user_id

Categories