Get data from three table SQL - php

My MySQL tables structure (3 table)
users
id
username
images
id
user_id
image
user_follow
id
user_id
follow_id
I try to do query which give me all images from "images" table from me (user_id = 3) and my friends which I follow "user_follow" table
Now query and it give me all pictures from user I follow, I do not know what changes to add to return also my images (my user_id = 3). All users names must be in username (not id), username is in "users" table
$sql = "SELECT u.username, p.image, p.date
FROM users u, user_follow f, images p
WHERE f.user_id = 3 AND f.follow_id = u.id AND f.follow_id = p.user_id
ORDER BY p.date DESC";
it return:
[0] => Array
(
[id] => 8
[image] => fsfsf
[date] => 2012-01-24 14:58:14
)
[1] => Array
(
[id] => 7
[image] => first.jpg
[date] => 2012-01-24 14:42:27
)
[2] => Array
(
[id] => 7
[image] => second.jpg
[date] => 2012-01-24 14:42:27
)
[3] => Array
(
[id] => 6
[image] => the_last.jpg
[date] => 2012-01-24 01:49:45
)
users and their images which I follow but no my images from my user_id

SELECT
images.*,
users.username
FROM images
LEFT JOIN users ON images.user_id = users.id
LEFT JOIN user_follow ON images.user_id = user_follow.follow_id
WHERE images.user_id = 3 OR user_follow.user_id = 3
ORDER BY images.date DESC

SELECT image
FROM images
WHERE user_id = 3
OR user_id IN (
SELECT follow_id
FROM user_follow
WHERE user_id = 3
)
ORDER BY date DESC;

Related

select GROUP_CONCAT in mysql

I have two tables:
table1:
id email
1 john#gmail.com
2 doe#gmail.com
table2:
userid key value
1 firstname john
1 phone 112233
2 firstname doe
2 phone 223344
This is mysql query without condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
This is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
array(
[id] => 2
[email] => doe#gmail.com
[userid] => 2
[key] => firstname,phone
[value] => doe,223344
)
This is mysql query with condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
WHERE b.key = "firstname"
AND b.value LIKE '%jo%'
And this is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname
[value] => john
)
But I want this:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
There any way to do this? thank for any help!
Your queries are lacking the GROUP BY clause to get a row per user. Then use a HAVING clause to make sure the aggregated row includes a firstname '%jo%':
SELECT a.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
GROUP BY a.id
HAVING sum(b.key = 'firstname'
AND b.value LIKE '%jo%') > 0;
true results in 1, false in 0 in MySQL. So checking whether the sum is greater than zero means checking whether the condition is true at least once.

How to use find in set for user rankings based on score?

I have query like this,
SELECT * FROM users ORDER BY score
So, the result is like this.
Array
(
[0] => stdClass Object
(
[userid] => 3
[user] => John Doe
[score] => 50
)
[1] => stdClass Object
(
[userid] => 1
[user] => Mae Smith
[score] => 38
)
[2] => stdClass Object
(
[userid] => 2
[user] => Mark Sam
[score] => 26
)
)
But, I want to add a rank using find_in_set query. So the result might be like this. So that the user can view their ranks when they login to their account.
Array
(
[0] => stdClass Object
(
[userid] => 3
[user] => John Doe
[score] => 50
[rank] => 1
)
[1] => stdClass Object
(
[userid] => 1
[user] => Mae Smith
[score] => 38
[rank] => 2
)
[2] => stdClass Object
(
[userid] => 2
[user] => Mark Sam
[score] => 26
[rank] => 3
)
)
I tried this one.
$listOfUser = array();
foreach($users as $user) {
$listOfUser[] = $user->userid;
}
And used another query
$userid = 2 // => id of loggedin user
SELECT *, find_in_set($userid, $listOfUser) as rank FROM users where userid=$userid ORDER BY score
So, I got this result
Array
(
[1] => stdClass Object
(
[userid] => 2
[user] => Mark Sam
[score] => 26
[rank] => 3
)
)
Which is somehow correct. But, is there another way of querying that result using only one SQL query and without using foreach loop?
Something like this.
$userid = 2 // => id of loggedin user
SELECT *, find_in_set($userid, (SELECT * FROM users ORDER BY score)) as rank FROM users where userid=$userid ORDER BY score
But I got this error Subquery returns more than 1 row
If You don't insist on using find_in_set, you can get result with simple join. You ask for list of users (p) and for each user you ask, how many users have better score than him or her (c):
SELECT p.userid, COUNT(c.userid) AS rank
FROM users AS p
LEFT JOIN users AS c ON c.score > p.score
GROUP BY p.userid
This works even if you add other conditions, like WHERE p.userid = 123.
If more users have the same score, the ranks would look like 0,1,2,2,2,5,6.
In your query, you can add counter, like this:
set #n:=0;
SELECT #i := #i + 1 AS rank, * FROM users ORDER BY score
The rank here is relative to the score distribution across all users. I believe you should try something originally proposed in this answer:
SELECT users.*,
#rownum := #rownum + 1 as rank
FROM users
CROSS JOIN (select #rownum := 0) r
ORDER BY score DESC
What it does is basically order all users by score, and assign each of them an incremental value "rank". So the top scorer would have a rank of 1, the second scorer would have a rank of 2 etc.
Keep in mind that this solution is not "fair" - each user will have a different rank, even if all users have the same score. If you try to rank users as they do in sports (if two top competitors have the same score, they both take 1st place, and the next best competitor takes 3rd place, not second), you should think of a different solution.

how to find last message from message table and also find users

This is my User table
This is my Message table
And tHis is my Listing Table
Now I get successfully get the last message with this query
enter code here
$coreQueryUser = $this->Message->query('
select m.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
');
when i run this query it gives me following output:-
enter code here
<pre>Array
(
[0] => Array
(
[m] => Array
(
[id] => 2
[sender_id] => 10
[reciever_id] => 21
[list_id] => 3
[message] => hello sir
[add_date] => 2016-09-25 08:24:38
[is_check] => 0
)
)
[1] => Array
(
[m] => Array
(
[id] => 7
[sender_id] => 10
[reciever_id] => 22
[list_id] => 3
[message] => hmm
[add_date] => 2016-09-27 00:00:00
[is_check] => 0
)
)
)
Now you see in the output in first array sender_id =10 and reciver_id = 21
and list_id = 3
List is created by user whose id is 10. in the output i want to fetch the User data whose user id 21. Remember that when reciever send the message to sender the ids are interchanging. in that case i also want the data of whose user id is 21
Please help me:(
Finallly i find the solution of my own
enter code here
$coreQueryUser = $this->Message->query('
select m.* ,u.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = " '. $data['list_id'] .'"
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
join
users u ON u.id = (CASE WHEN m.sender_id = 10
THEN m.reciever_id
ELSE m.sender_id
END)
');

SQL left join part of the array is empty

My problem is the following code the comment&rating area of the array should have a comment in it as the DB history table does ...?
SELECT users.uid, users.username, history.user_id, history.comment, history.rating
FROM history
LEFT JOIN users
ON users.uid=history.user_id
WHERE history.book_id="$bid"
It returns :
Array ( [uid] => 3 [username] => Reign [user_id] => 3 [comment] => [rating] => )
Then you want to use an INNER JOIN. A LEFT JOIN will return NULL values.
SELECT users.uid, users.username, history.user_id, history.comment, history.rating
FROM history
INNER JOIN users
ON users.uid=history.user_id
WHERE history.book_id="$bid"

return data from different table sql to html

My users have pages:
user favorites
users image
I try to do a page "everything" which will get data from 2 sql tables (already have sql code) to one html page ordering all by date. Problem is that "user image" have one html structure and "user favorites" another. Many website have such pages where is output different data in different html structure from different tables. Today I first time tried to do this and do not know the correct way.
My tables:
users
id
username
images
id
user_id
image
description
date <--- uplaod date
user_favorites
id
user_id <---user id who like image
image_id <---id of liked image
date <---date when image was clicked "liked"
I get user images with this sql
function users_pictures($user_id)
{
$sql = "SELECT username as user, p.image as user_image, i.image, i.id as image_id, i.description as text, UNIX_TIMESTAMP(i.date) as image_date, COALESCE ( imgcount.cnt, 0 ) as comments
FROM users u
LEFT JOIN images i ON i.user_id = u.id
LEFT JOIN images p ON p.id = (SELECT b.id FROM images AS b where u.id = b.user_id ORDER BY b.id DESC LIMIT 1)
LEFT JOIN (SELECT image_id, COUNT(*) as cnt FROM commentaries GROUP BY image_id ) imgcount ON i.id = imgcount.image_id
WHERE i.user_id = ?
ORDER BY i.date DESC";
$query = $this->db->query($sql, $user_id);
return $query->result_array();
}
I get all users image and user current image - avatar (last upload image is user avatar)
return example :
[images_list] => Array
(
[0] => Array
(
[user] => 8888
[user_image] => http://127.0.0.1/auth_system_1/upload_images/24/24_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[image] => http://127.0.0.1/auth_system_1/upload_images/224/224_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[image_id] => 4
[text] =>
[image_date] => 50 minutes
[comments] => 0
[user_first_image] => 1
)
)
User favorite table is :
function users_favorites_list($user_id)
{
$sql = "SELECT
u.username as user,
p.image as user_image,
fav.id as favorite_id,
UNIX_TIMESTAMP(fav.date) as favorite_date,
i.id as images_id,
i.image,
i.description as text,
u2.username as favorite_user,
t.image as favorite_user_image
FROM users u
LEFT JOIN user_favorites fav ON fav.user_id = u.id
LEFT JOIN user_follow f ON f.follow_id = fav.user_id
LEFT JOIN images i ON i.id = fav.image_id
LEFT JOIN users u2 ON u2.id = i.user_id
LEFT JOIN images p ON p.id = (SELECT b.id FROM images AS b where fav.user_id = b.user_id ORDER BY b.id DESC LIMIT 1)
LEFT JOIN images t ON t.id = (SELECT b.id FROM images AS b where u2.id = b.user_id ORDER BY b.id DESC LIMIT 1)
WHERE fav.user_id = ?
GROUP BY fav.id
ORDER BY fav.date DESC";
$query = $this->db->query($sql, array($user_id, $user_id));
return $query->result_array();
}
return example:
Array
(
[0] => Array
(
[user] => 8888
[user_image] => http://127.0.0.1/auth_system_1/upload_images/24/24_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[favorite_id] => 5
[favorite_date] => 18 minutes ago
[images_id] => 2
[image] => http://127.0.0.1/auth_system_1/upload_images/100/100_flw3utn9igiqh7dtt2o61ydf8_174.jpeg
[text] => 3
[favorite_user] => 6666
[favorite_user_image] => http://127.0.0.1/auth_system_1/upload_images/24/24_flw3utn9igiqh7dtt2o61ydf8_174.jpeg
)
[1] => Array
(
[user] => 8888
[user_image] => http://127.0.0.1/auth_system_1/upload_images/24/24_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[favorite_id] => 2
[favorite_date] => 1 week ago
[images_id] => 4
[image] => http://127.0.0.1/auth_system_1/upload_images/100/100_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[text] =>
[favorite_user] => 8888
[favorite_user_image] => http://127.0.0.1/auth_system_1/upload_images/24/24_0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
)
)
:
![My html structure where I try to return data from 2 sql][1]
I need select user activities from 2 table in one page with different html structures (example see image) . I think many peole do it. Please tell me how to do this?
[everything_list] => Array
(
[0] => Array
(
[user] => 8888
[user_image] => 0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[favorite_id] => 5
[favorite_date] => 1328565406
[images_id] => 2
[image] => flw3utn9igiqh7dtt2o61ydf8_174.jpeg
[text] => 3
[favorite_user] => 6666
[favorite_user_image] => flw3utn9igiqh7dtt2o61ydf8_174.jpeg
)
[1] => Array
(
[user] => 8888
[user_image] => 0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[favorite_id] => 2
[favorite_date] => 1327856547
[images_id] => 4
[image] => 0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
[text] =>
[favorite_user] => 8888
[favorite_user_image] => 0j1kjjzdv3ez07a0ee4lnmjb7_163.jpeg
)
)
The query below return what you need?
SELECT
username as user,
p.image as user_image,
i.image,
i.id as image_id,
i.description as text,
UNIX_TIMESTAMP(i.date) as image_date,
COALESCE ( imgcount.cnt, 0 ) as comments,
fav.id as favorite_id,
UNIX_TIMESTAMP(fav.date) as favorite_date,
u2.username as favorite_user,
t.image as favorite_user_image
FROM users u
LEFT JOIN user_favorites fav ON fav.user_id = u.id
LEFT JOIN user_follow f ON f.follow_id = fav.user_id
LEFT JOIN images i ON i.user_id = u.id
LEFT JOIN users u2 ON u2.id = i.user_id
LEFT JOIN images p ON p.id = (SELECT b.id FROM images AS b where u.id = b.user_id ORDER BY b.id DESC LIMIT 1)
LEFT JOIN (SELECT image_id, COUNT(*) as cnt FROM commentaries GROUP BY image_id ) imgcount ON i.id = imgcount.image_id
LEFT JOIN images t ON t.id = (SELECT b.id FROM images AS b where u2.id = b.user_id ORDER BY b.id DESC LIMIT 1)
WHERE u.user_id = ?
GROUP BY fav.id
ORDER BY i.date DESC

Categories