MySQL Query - a bit tricky - php

i'm having the following tables:
USERS: ITEMS
user_id name always_show id user_id name
-------------------------- --------------------------------
1 Joe 1 1 Apple
2 Sam 2 1 Banana
3 Walter 1 3 2 Cherry
i'm doing this query:
SELECT * FROM
users Inner Join
items On users.user_id = items.user_id
The question is: how can i add all other users which have the flag always_show set?

i hope i understand your question :-) try UNION
SELECT u.* FROM users u
INNER JOIN items i ON u.user_id = i.user_id
UNION ALL SELECT * FROM users WHERE always_show = 1

SELECT * FROM
users Inner Join
items On users.user_id = items.user_id where Users.always_set = 1

SELECT *
FROM users
INNER JOIN items On users.user_id = items.user_id
UNION
SELECT *
FROM users
LEFT OUTER JOIN items On users.user_id = items.user_id AND users.always_show = 1

Related

not able to select count with case condition

I have the two tables:
user_groups
id name created_user
1 gn1 3
2 gn2 3
user_group_has_users
group_id user_id
2 5
2 6
I want to count the users per group and an output similar this:
id name user_count
2 gn2 2
1 gn1 0
I tried this query
select g.*,
count(cg.user_id) as user_count
from user_groups as g
left join user_group_has_users as cg on cg.user_group_id = g.id
where g.created_user = 3
But it only returns one row. I do not understand why this happening.
Please help me on this.
Use this query
SELECT g.* ,COUNT(cg.user_id) AS user_count
FROM user_groups g
LEFT JOIN user_group_has_users cg ON cg.group_id = g.id
WHERE g.created_user = 3
GROUP BY g.id
ORDER BY user_count DESC ;
Left join with where condition is nothing but inner join. You may want as
select
ug.id,
ug.name,
count(ughu.user_id) as user_count
from user_groups ug
left join user_groups_has_users ughu on ughu.group_id = ug.id
and ug.created_user = 3
group by ug.id
order by user_count desc ;
If you still want to filter the data with the created_user = 3 then use inner join and move the condition to where clause
Be careful with aggregates and JOINs. In some cases the numbers are inflated.
See if this works for you:
select g.*,
( SELECT count(*)
FROM user_group_has_users
WHERE user_group_id = g.id
) AS user_count
from user_groups as g
where g.created_user = 3

Slow query using "where in" and "order by select count"

I want to show post from users that specified user is followed and i have two tables at below. but its query is very slow.
table user
id | username
1 | name1
2 | name2
3 | name3
..
..
table post
id | poster_id | post_content
1 | 2
2 | 3
3 | 10
..
..
table follow
followerid | followtoid
1 | 2
1 | 3
2 | 10
..
..
Assume that all tables have more than 1000 rows.
This's SQL
SELECT *
FROM post
WHERE poster_id IN (
SELECT followtoid
WHERE followerid = $_SESSION['userid']
)
And this's the second cast is very slow too.
I want to list all member by order from their total posts.
SELECT *
FROM user
ORDER BY (
SELECT COUNT(id)
FROM post
WHERE post_id = user.id
) DESC;
Try indexing post.userid, post.poster_id, followtoid.followerid and user.user_id, using CREATE INDEX, and use LEFT JOIN clause on your queries instead:
SELECT *
FROM user u
LEFT JOIN SELECT poster_id, COUNT(*) as count FROM post p GROUP BY poster_id
ON (u.user_id = p.poster_id)
ORDER BY count DESC;
and:
SELECT * FROM post AS p
LEFT JOIN (SELECT followerid FROM followtoid) AS f
ON (p.userid=f.followerid)
WHERE p.userid = {$_SESSION['userid']}
Use a JOIN for the first query
SELECT p.*
FROM post p
JOIN follow f ON p.post_id = f.followtoid
WHERE f.followerid = $_SESSION['userid']
and a JOIN plus a GROUP BY for the second
SELECT u.*, tbl.postCount
FROM user u
JOIN (
SELECT poster_id, COUNT(*) AS postCount
FROM post p
GROUP BY posterID
) tbl ON tbl.poster_id = u.id
ORDER BY postCount DESC
You can accomplish the second query without a subquery:
SELECT u.*, COUNT(p.poster_id) as postCount
FROM user u
LEFT JOIN post p
ON (u.user_id = p.poster_id)
GROUP BY u.user_id
ORDER BY postCount DESC;

Get random friends from mysql

There where 2 mysql tables users(id,name,city) and friend_list(id,userid,friend,status).
Now i need to get three random friends from the friend_list table and their name from users table.
Friend_list table
id | userid |friend |status
1 | 1 | 2 | friends
2 | 3 | 1 | friends
3 | 2 | 3 | friends
users table:
id | name
1 | xxx
2 | yyy
3 | zzz
I need query something like this.
SELECT f.*,u.name FROM friend_list f,users u WHERE (f.userid = 1 or f.friend = 1) AND f.status = 'friends' AND f.userid = u.id AND f.order by RAND() limit 3
but for eg: it should select 1 in userid column and also from friend column.
I m trying to achieve it without using JOIN's
You can use the oreder by rand() as in below query.
select Friend_list.friend,users.name from Friend_list inner join users on Friend_list.userid=users.id order by rand();
To select 2 random entries try:
SELECT * FROM
(
SELECT * from users join on Friend_list.userid = users.id where users.id = ?
) as sub_equity
ORDER BY RAND() LIMIT 2
I had a same task on a project :-)
SELECT Friend_list.*, users.name
FROM Friend_list INNER JOIN users ON Friend_list.userid = users.id
ORDER BY RAND() // this will show random records
You can use ORDER BY RAND() LIMIT 3;
Try this:
SELECT * FROM friend_list f
INNER JOIN users u ON u.id = f.userid
ORDER BY rand() LIMIT 1;
SQL FIDDLE: http://sqlfiddle.com/#!2/e483c/1/0
ORDER BY RAND() is quite slow if there are many rows.
If users.id is sequential and you have statistic on users.id (e.g. MAX(users.id), MIN(users.id)), generate three random number between min, max in client side.
And following query:
SELECT u.name as person, u2.name as friend_with
FROM users u
INNER JOIN friends_list f ON u.id = f.userid
WHERE users.id IN (random_number1, 2, 3);
this query can use INDEX, so it's faster than ORDER BY RAND()
ah.. users.id would not be continuous (e.g user deleted), so you need to generate enough random number.
Try doing this:
SELECT u.name as person, u2.name as friend_with
FROM users u
INNER JOIN friends_list f ON u.id = f.userid
INNER JOIN users u2 ON u2.id = f.friend
WHERE f.userid = 1 or f.friend = 1
AND f.status = 'friends'
ORDER BY rand() LIMIT 3;
SQLFIDDLE DEMO
This will get you three random records with the name of the person and the name of his friend, being one of the userid 1

Getting a list of friend's names from MySQL

I have a table named friends;
friends
id uid fid
1 1 2 (1 is a friend of 2 and vice versa)
2 1 3 (1 is a friend of 3 and vice versa)
3 4 1 (1 is a friend of 4 and vice versa)
4 5 1 (1 is a friend of 5 and vice versa)
And a corresponding table for users;
users
uid name
1 mike
2 john
3 karl
4 mary
5 tony
This doesn't seem to do the trick:
SELECT name FROM users LEFT JOIN friends ON friends.uid=users.uid WHERE friends.uid='1' OR friends.fid='1'
What should my query be to get all the names of mike's friends?
This should do it just fine with a single, easy to index, query;
SELECT name FROM users u
JOIN friends f
ON u.uid = f.uid OR u.uid = f.fid
WHERE (f.uid=1 OR f.fid=1)
AND u.uid<>1;
Demo here.
Untested:
SELECT name from friends LEFT JOIN users on users.uid=friends.fid where friends.uid=1 UNION
SELECT name from friends LEFT JOIN users on users.uid=friends.uid where friends.fid=1
This may look a little strange if anyone is ever friends with themselves.
try one of these:
SELECT a.uid as UserID,
a.`Name` as UserName,
c.`Name as FriendsName
FROM users a LEFT JOIN friends b on a.uid = b.uid
LEFT JOIN users c on b.fid = c.uid
OR
SELECT a.uid as UserID,
a.`Name` as UserName,
GROUP_CONCAT(c.`Name`) as FriendsList
FROM users a LEFT JOIN friends b on a.uid = b.uid
LEFT JOIN users c on b.fid = c.uid
GROUP BY a.uid
As in your prequel question, you need to cover both foreign keys to the user table to get all his friends:
SELECT users.*
FROM (
SELECT uid FROM friends WHERE fid = 1
UNION ALL
SELECT fid FROM friends WHERE uid = 1
) f
JOIN users USING (uid)
Switch friends and users in your query and I think you'll get what you want.
In other words:
SELECT name FROM friends LEFT JOIN users ON friends.uid=users.uid WHERE friends.uid='1' OR friends.fid='1'
I think this is right SELECT name FROM users LEFT JOIN friends ON friends.uid=users.uid WHERE friends.uid=1 OR friends.fid=1

mysql joining two table

table user:
id_u* f_name l_name
----------------------
1 andi mitchel
2 sarah bench
3 kirsty larx
table voucher:
id_v* id_user id_target
1 1 2
2 2 3
quite confused how to join those table with two foreign keys
$db->query("SELECT * FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user
LEFT JOIN user u1 ON u1.id_u = v.id_target
WHERE .... ")
echoing while loop... and returns nothing??
while($r = $q->fetch_array(MYSQLI_ASSOC)) :
echo $r['u.f_name'];
echo $r['u1.f_name'];
endwhile;
Your JOIN seems absolutely correct. The only issue is that you have joined table user twice, therefore you have columns with same name (like f_name). The database will assign different (but arbitrary) names to these columns. You can override this behaviour with the AS keyword:
$db->query("SELECT v.*
, u.f_name AS user_f_name
, u.l_name AS user_l_name
, ta.f_name AS target_f_name
, ta.l_name AS target_l_name
FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user
LEFT JOIN user ta ON ta.id_u = v.id_target
WHERE .... ")
Then:
while($r = $q->fetch_array(MYSQLI_ASSOC)) :
echo $r['user_f_name'];
echo $r['target_f_name'];
endwhile;
And I think you can replace the LEFT JOINs with (inner) JOINs. Unless you have id_user or id_target values referencing non-existing userids (id_u).
It looks like you are asking for all people who are in the voucher table regardless of them being in position 1 (user) or position 2 (target)... Then, showing that person's name.
This query does a pre-query of each possible person and their position basis (via WhichPosition).
SELECT STRAIGHT_JOIN
AllVoucherUsers.WhatPosition,
u.*
FROM
( select distinct
v.id_user,
'1' as WhatPosition
from voucher v
union select distinct
v.id_target as id_user,
'2' as WhatPosition
from voucher v
) AllVoucherUsers
join users u
on AllVoucherUsres.id_user = u.id_u
If you only want ONE instance of a given person -- REGARDLESS of their position, just strip out all instances of the "WhatPosition" reference...
SELECT STRAIGHT_JOIN
u.*
FROM
( select distinct
v.id_user
from voucher v
union select distinct
v.id_target as id_user
from voucher v
) AllVoucherUsers
join users u
on AllVoucherUsres.id_user = u.id_u
SELECT * FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user OR u.id_u = v.id_target
WHERE ....
how about:
SELECT * FROM voucher JOIN user ON id_user = id_u
Simpler still:
SELECT * FROM voucher, user WHERE id_user = id_u

Categories