Lets say that given a song_id and a uid, we would like to know all friends (direct friends and friends of frinds) that like the same song:
This is how we are doing it:
public function get_song_mates($uid, $song_id, $current_only = true, $limit = PHP_INT_MAX)
{
$sql = "SELECT *
FROM (
(
SELECT users . * , '1st' AS `level`, 1 AS `level_i`
FROM songs
JOIN users ON users.id = songs.user_id
JOIN friends AS my_friend ON my_friend.fid = users.id
AND my_friend.uid = '".$uid."'
WHERE song_id = '".$song_id."')
UNION (
SELECT second_friend . * , '2nd' AS `level`, 2 AS `level_i`
FROM songs
JOIN users AS second_friend ON second_friend.id = songs.user_id
JOIN friends ON friends.uid = second_friend.id
JOIN users AS first_friend ON first_friend.id = friends.fid
JOIN friends AS my_friend ON my_friend.fid = first_friend.id
AND my_friend.uid = '".$uid."'
WHERE song_id = '".$song_id."'
AND second_friend.id NOT IN
(
SELECT users.id
FROM songs
JOIN users ON users.id = songs.user_id
JOIN friends AS my_friend ON my_friend.fid = users.id
AND my_friend.uid = '".$uid."'
WHERE song_id = '".$song_id."'
)
) ORDER BY `level_i` ASC, firstname, lastname
) AS friend
GROUP BY id ORDER BY `level_i`";
$users = $this->getFromSql($sql);
return $users;
}
But please note we had to add:
AND second_friend.id NOT IN...
to prevent showing same user as direct friend and as a friend of friend.. i am pretty sure i need to make use of GROUP BY, but i just can't get with the right syntax. any clue here?
-EDIT-
friends(uid, fid)
songs(id, user_id, song_id)
users(id, frist_name, last_name)
Fixed it like this:
public function get_song_mates($uid, $song_id, $current_only = true, $limit = PHP_INT_MAX)
{
$sql = "SELECT DISTINCT *
FROM (
(
SELECT users . * , '1st' AS `level`, 1 AS `level_i`
FROM songs
JOIN users ON users.id = songs.user_id
JOIN friends AS my_friend ON my_friend.fid = users.id
AND my_friend.uid = '".$uid."'
WHERE song_id = '".$song_id."')
UNION (
SELECT DISTINCT second_friend . * , '2nd' AS `level`, 2 AS `level_i`
FROM songs
JOIN users AS second_friend ON second_friend.id = songs.user_id
JOIN friends ON friends.uid = second_friend.id
JOIN users AS first_friend ON first_friend.id = friends.fid
JOIN friends AS my_friend ON my_friend.fid = first_friend.id
AND my_friend.uid = '".$uid."'
WHERE song_id = '".$song_id."'";
$users = $this->getFromSql($sql);
return $users;
}
Related
I want to display posts from the users being followed and the logged in user using a single PHP MySql query.
I have three tables:
users (user_id, username, ..)
posts (post_id, content, added_by, ..)
Followers (f_id, followed, followed_by)
I have variable
$id = $_SESSION['user_id']
$que = $db->prepare("SELECT posts.*, users.*, followers.follow, followers.followed_by FROM posts
INNER JOIN users ON users.user_id = posts.added_by_user_id
LEFT JOIN followers ON followers.follow = posts.added_by_user_id
WHERE (posts.added_by_user_id = $id OR followers.followed_by = $id) ORDER BY post_id DESC");
$que->execute();
$posts = $que->fetchAll();
But the query shows each post created by logged-in user twice.
You can use any of the following:
Add additional clause to you LEFT JOIN followers and it will do the trick i.e LEFT JOIN followers ON ( followers.follow = posts.added_by_user_id AND followers.followed_by = $id ) . Note the AND
$que = $db->prepare("SELECT posts.*, users.*, followers.follow, followers.followed_by FROM posts
INNER JOIN users ON users.user_id = posts.added_by_user_id
LEFT JOIN followers ON ( followers.follow = posts.added_by_user_id
AND followers.followed_by = $id )
WHERE (posts.added_by_user_id = $id OR followers.followed_by = $id)
GROUP BY( posts.post_id )
ORDER BY post_id DESC");
$que->execute();
$posts = $que->fetchAll();
Anotber way using your code, just add DISTINCT after SELECT. I.e SELECT DISTINCT posts.* .....
Another way is using sub query
$que = $db->prepare("SELECT posts.*, users.* FROM posts
INNER JOIN users ON users.user_id = posts.added_by_user_id
WHERE posts.added_by_user_id= $id OR posts.added_by_user_id IN (SELECT follow FROM followers WHERE followed_by= $id)
ORDER BY post_id DESC");
$que->execute();
$posts = $que->fetchAll();
You can also use the below. The key function is GROUP BY
$que = $db->prepare("SELECT posts.*, users.*, followers.follow, followers.followed_by FROM posts
INNER JOIN users ON users.user_id = posts.added_by_user_id
LEFT JOIN followers ON followers.follow = posts.added_by_user_id
WHERE (posts.added_by_user_id = $id OR followers.followed_by = $id)
GROUP BY( posts.post_id )
ORDER BY post_id DESC");
$que->execute();
$posts = $que->fetchAll();
(I'm not too sure how efficient this is)
Here is my query worked well but want to add another condition in it but it giving error Not unique table/alias: 'users'
Here is my code
$query = 'select group_concat(DISTINCT evaluation_section. section_name) as allowed_sections from evaluation_section
join section_permissions on (section_permissions.section_id = evaluation_section.section_id )
join users on ( users.user_id = section_permissions.user_id )
join users on ( users.user_id = section_permissions.assigned_for )
where users.user_id = '.$user['user_id'];
want select name from users table also and then use this condition join users on (users.user_id = section_permissions.assigned_for )
please help me
This is my edited text
this is my full working query
$q = 'select group_concat(DISTINCT evaluation_section. section_name) as allowed_sections from evaluation_section
join section_permissions on (section_permissions.section_id = evaluation_section.section_id )
join users on ( users.user_id = section_permissions.user_id )
where users.user_id = '.$user['user_id'];
but i want it to select name from users table and then match it with users.user_id = section_permissions.assigned_for so that it get the name of assigned_for id name
as before group_concat I use users.name then its working but it display the name of users.user_id = section_permissions.user_id but i want to display name of er_id )
where users.user_id = '.$user['user_id'];
but i want it to select name from users table and then match it with users.user_id = section_permissions.assigned_for
in same query because in two its not working
Try doing it this way:
$query = 'select group_concat(DISTINCT evaluation_section. section_name) as allowed_sections from evaluation_section
join section_permissions on (section_permissions.section_id = evaluation_section.section_id )
join users u1 on ( u1.user_id = section_permissions.user_id )
join users u2 on ( u2.user_id = section_permissions.assigned_for )
where u1.user_id = '.$user['user_id'];
Since you are joining "users" table twice, you will have to provide unique alias name to both of them.
How to write this query in laravel 5.1
SELECT
(SELECT firstname FROM registration_details a INNER JOIN users b
ON a.id = b.registerid
WHERE c.patientid = b.id ) AS patient,
(SELECT firstname FROM registration_details a INNER JOIN users b
ON a.id = b.registerid
WHERE c.doctorid = b.id ) AS doctor,
c.`appoinmentdate`
FROM `appoinments` c
I tried like this But i get Undefined property: stdClass::$id error
DB::table('appoinments')
->select(DB::raw(
"(SELECT firstname FROM registration_details INNER JOIN users ON registration_details.id = users.registerid WHERE appoinments.patientid = users.id) AS patient",
"(SELECT firstname FROM registration_details INNER JOIN users ON registration_details.id = users.registerid WHERE appoinments.doctorid = users.id) As doctor",
"appoinments.appoinmentdate",
"appoinments.id",
"(SELECT timings FROM appoinment_time WHERE appoinment_time.id = appoinments.appoinment_time) AS apptime ",
"(SELECT branchname FROM branches WHERE branches.id = appoinments.branchcode) AS branch"))
->get();
Finally got the answer. Thanks to all who try for me.
$appoinment = DB::table('appoinments')->select(DB::raw("(SELECT firstname FROM registration_details INNER JOIN users ON registration_details.id = users.registerid WHERE appoinments.patientid = users.id) AS patientid"));
$appoinment = $appoinment->addSelect(DB::raw("(SELECT firstname FROM registration_details INNER JOIN users ON registration_details.id = users.registerid WHERE appoinments.doctorid = users.id) As doctorid"));
$appoinment = $appoinment->addSelect(DB::raw("appoinments.appoinmentdate"));
$appoinmentlist = $appoinment3->addSelect(DB::raw("appoinments.id"))->get();
For my mobile App i am using a web service to get the images and all records from the MySQL database, its like Instagram.
But SELECT DISTINCT taking more than 7 - 8 seconds.is there any thing that i can do for reduce the time?
SELECT distinct count(*) as totalrecord ,p.description,p.photo_id ,p.user_id,p.imagepath1 ,p.friends, p.is_report_photo,
p.imagepath2,p.imagepath3,p.imagepath4,p.imagepath5,p.count_comment,p.count_like,p.created as photo_created ,
(select username from users where id = p.user_id) as username ,
(select country from users where id = p.user_id) as country,
(select email from users where id = p.user_id) as email ,
(select image_path from users where id = p.user_id) as image_path ,
(select gender from users where id = p.user_id) as gender,
(select privacy from users where id = p.user_id) as privacy,
(select audio_privacy from users where id = p.user_id) as audio_privacy,
(select video_privacy from users where id = p.user_id) as video_privacy,
(select photo_privacy from users where id = p.user_id) as photo_privacy,
If(pl.user_id && pl.photo_id !='',like_status,0) as islike ,
If(pr.user_id && pr.photo_id !='',1,0) as isreport,
p.user_visibility
from friends as fr
inner join users as u on u.id = (select distinct if (fr.user_id != $user_id,fr.user_id,(fr.to_user_id)) as rd
from friends) && fr.read_status = '1'
inner join photos as p on (p.user_visibility = 'p')
LEFT JOIN photolike as pl ON pl.photo_id = p.photo_id && pl.user_id = $user_id
LEFT JOIN photo_report as pr on pl. photo_id = pr.photo_id && pr.user_id = $user_id
ORDER BY p.photo_id DESC;
Use mysql indexing that will reduce the time
Try using group-by clause instead of distinct.
I have the following SQL:
SELECT (
(SELECT SUM(vote_score)
FROM question_votes
JOIN questions
ON vote_question = q_id
JOIN users
ON q_author = users.id
WHERE q_author` = users.id)
+
(SELECT SUM(vote_score)
FROM answer_votes
JOIN answers
ON vote_answer = a_id
JOIN users
ON a_author = users.id
WHERE a_author = users.id)) AS rep
and I want it to be added here (Ion Auth's method):
$this->db->select(
array(
$this->tables['users'].'.*',
$this->tables['groups'].'.name AS '. $this->db->protect_identifiers('group'),
$this->tables['groups'].'.description AS '. $this->db->protect_identifiers('group_description'),
"(SELECT COUNT(`a_author`) FROM `answers` WHERE a_author = users.id) + (SELECT COUNT(`q_author`) FROM `questions` WHERE q_author = users.id ) AS total_posts",
"SELECT
((SELECT SUM(vote_score)
FROM question_votes
JOIN questions
ON vote_question = q_id
JOIN users
ON q_author = users.id
WHERE q_author` = users.id)
+
(SELECT SUM(vote_score)
FROM answer_votes
JOIN answers
ON vote_answer = a_id
JOIN users
ON a_author = users.id
WHERE a_author = users.id)) AS rep"
)
);
but I get the followin error:
Did you read the error message?
You have a (`) where shouldn't be any.
Change this: WHERE q_author' = users.id for this: WHERE q_author = users.id