In my database I have a table (likes) that lists items that users have liked.
When visiting a users profile I need to determine how many of those "likes" we have in common.
What's the best way to go about writing a query that will display the mutual likes between users?
likes table
id | user | item | activated
-----------------------------------
1 | 3 | 14 | 1
2 | 4 | 14 | 1
I need to return 14 in this example.
Suppose should be something like this:
select userViewer.item, items.itemName
from likes userViewer,
likes userProfile,
items
where userProfile.user = $profileUserId
and userViewer.user = $userViewer
and userProfile.item = userViewer.item
and items.item = userViewer.item
where $profileUserId - userId of the profile user and $userViewer - userId of current user
Same query on "join on" form with "items" table, as example:
select userViewer.item, items.itemName
from likes userViewer inner join likes userProfile
on userProfile.user = $profileUserId
and userViewer.user = $userViewer
and userProfile.item = userViewer.item
inner join items
on userViewer.item = items.item
I wants to know why you have not used matching caondition in where clause
SELECT
userViewer.item, items.itemName
FROM
likes AS userViewer
INNER JOIN
likes as userProfile
ON
userProfile.item = userViewer.item
INNER JOIN items
ON
userViewer.item = items.item
WHERE
userViewer.user = $userViewer
AND
userProfile.user = $profileUserId
Related
I am new at MySQL, but I was testing out and creating a somewhat of a group function that you see in eg.: 'Facebook'. And I wanted to display a listing of all the Group Posts that the logged in User joined, and how many comments it has.
Tables:
group_table -> contains all the groups
user_table -> contains all the users
group_users -> now, this contains each users that are linked to each group
eg: groupuser: 1 | groupid: 4 | admin: 1 (bool)
post_table -> contains all the posts
comment_table -> contains all the comments
So... this was my attempt at it:
SELECT pt.postid, pt.postcont, pt.ctime, gt.groupname,
COUNT(cm.commid) AS commNumber
FROM post_table pt
INNER JOIN group_users gu
ON pt.gid = gu.gid
INNER JOIN group_table gt
ON gu.gid = gt.gid
LEFT JOIN comment_table cm
ON pt.postid = cm.postid
WHERE gu.groupuserid = {user_id}
What I want the results to show:
postid | postcontent | ctime | groupname | commentNumber
1 loremipsum {date} coolgroup if there is any comment then display {nr of comments otherwise 0}
but at the moment, the problem is that only the posts that contain a comment are being retrieved and showing in the results (commNumber is correct), but those who don't have a comment instead of showing '0' for commNumber, the post itself isn't being retrieved
I have these two tables - user_schedules and user_schedule_meta, shown below:
------------------------------------
| id | scheduler_id | status |
------------------------------------
1 3 pending
2 5 active
3 6 active
and
----------------------------------------------
| id | user_schedule_id | meta_key |meta_value
----------------------------------------------
1 3 course-id 135
2 3 session-id 15
3 3 schedule-id 120
I want to write a query to enable me select, for example, from both tables where EVERYONE of the below 5 conditions are met:
user_schedule_id = 3
scheduler_id = 6
session_id = 15
course-id = 135
schedule-id = 120
This is what I have so far, but it is not working:
SELECT user_schedule_meta.`id` FROM user_schedule_meta, user_schedules
WHERE user_schedules.`scheduler_id` = 6
AND user_schedules.id = user_schedule_meta.`user_schedule_id`
AND (
(user_schedule_meta.`meta_key` = 'course-id' AND user_schedule_meta.`meta_value` = 135)
OR (user_schedule_meta.`meta_key` = 'session-id' AND user_schedule_meta.`meta_value` = 15)
OR (user_schedule_meta.`meta_key` = 'daily-schedule-id' AND user_schedule_meta.`meta_value` = 120)
)
GROUP BY user_schedule_meta.`id`
Any suggestions what I am not doing right?
This is a typical key-value store lookup problem. These are trickier than they look in SQL, in that they require multiple JOIN operations.
You need a virtual table with one row per user_schedules.id value, then you can filter it. So
SELECT u.id, u.scheduler_id
FROM user_schedules u
JOIN user_schedule_meta a ON u.id=a.user_schedule_id AND a.meta_key='course-id'
JOIN user_schedule_meta b ON u.id=b.user_schedule_id AND b.meta_key='session-id'
JOIN user_schedule_meta c ON u.id=c.user_schedule_id AND c.meta_key='daily-schedule-id'
WHERE a.meta_value = 135 -- value associated with course-id
AND b.meta_value=15 -- value associated with session-id
AND c.meta_value=120 -- value associated with daily-schedule-id
Notice also that you can list your table with associated attributes like this. This trick of joining the key/value table multiple times is a kind of pivot operation. I use LEFT JOIN because it will allow the result set to show rows where an attribute is missing.
SELECT u.id, u.scheduler_id, u.status,
a.meta_value AS course_id,
b.meta_value AS session_id,
c.meta_value AS daily_schedule_id
FROM user_schedules u
LEFT JOIN user_schedule_meta a ON u.id=a.user_schedule_id AND a.meta_key='course-id'
LEFT JOIN user_schedule_meta b ON u.id=b.user_schedule_id AND b.meta_key='session-id'
LEFT JOIN user_schedule_meta c ON u.id=c.user_schedule_id AND c.meta_key='daily-schedule-id'
try this is code
select * from user_schedule_meta where user_schedule_id=3 and
(meta_key='session-id' AND meta_value=15
or meta_key='daily-schedule-id' AND meta_value=120
or meta_key='course-id' AND meta_value=135
)
I have this query:
SELECT *
FROM `classes`
JOIN `classes_students`
ON `classes`.`id` = `classes_students`.`class`
And I need to add condition for selecting just classes, in which are not currently logged student (user ID is not in classes_students connected with class id) and also count how many students are in that class.
Table structure:
classes: id, name, etc
classes_students: class_id, user_id, etc
Table data:
classes:
1 | test
2 | test2
3 | test3
classes_students:
1 | 1
1 | 2
2 | 3
3 | 4
3 | 5
Expected output if im user with id 1:
classes names (with number of students in):
2 (1 student)
3 (2 students)
All this in one query. It is possible? If yes, how?
Select classid, count(*)
from class
left join student on student.classid = class.classid
group by classid
Glad help for you
Try this query:
$user_id = 1; // current user_id
$query = "SELECT `classes`.`id`, `classes`.`name`, COUNT(*) as students FROM `classes`
JOIN `classes_students`
ON `classes`.`id` = `classes_students`.`class_id`
AND `classes_students`.`user_id` != $user_id
GROUP BY `classes_students`.`class_id`
";
I figured it out! :)
Thank you guys for ur help.
$user_id = 1; // current user_id
$query = "SELECT `classes`.`id`, `classes`.`name`, COUNT(*) as students FROM `classes`
LEFT JOIN `classes_students`
ON `classes`.`id` = `classes_students`.`class_id`
WHERE `classes`.`id` NOT IN (SELECT `class_id` FROM `classes_students` WHERE `user_id`='.$user_id.')
GROUP BY `classes_students`.`class_id`
";
I'm not getting any data, and I've checked my dad which should match up
I have two tables, likes and user_follow
I'm trying to tie the two tables by an id.
Table - Column
likes - idlikes, iduser, information
user_follow - iduser_follow, iduser_follower, iduser_following
$following = $dbh -> prepare("SELECT L.* FROM likes L JOIN user_follow F ON F.iduser_following = L.iduser WHERE F.iduser_follower = ?");
$following->execute(array($_SESSION['user_auth']));
while($row_following = $following->fetch(PDO::FETCH_ASSOC)){
$id_1 = $row_following['L.information']; // get id of user that i'm following
echo $id_1;
}
So if i'm following someone, i should be able to display information associated with whomever I'm following.
I don't get any errors, it just doesn't echo out anything?
Sample Data
user_follow
iduser_follow iduser_follower iduser_following
1 2 3
2 2 4
likles
idlikes iduser information
1 3 info1
2 3 info2
So, I should output info1 and info2, assuming that $_SESSION['user_auth'] = 2, correct?
SELECT b.*
FROM user_follow a
INNER JOIN likes b
ON a.iduser_following = b.iduser
WHERE a.iduser_follow = 'myuserID' AND
iduser_following = 'followingID'
and fetch value
$id_1 = $row_following['information'];
Any time there is an update within my music community (song comment, artist update, new song added, yadda yadda yadda), a new row is inserted in my "updates" table. The row houses the artist id involved along with other information (what type of change, time and date, etc).
My users have a "favorite artists" section where they can do just that -- mark artists as their favorites. As such, I'd like to create a new feature that shows the user the changes made to their various favorite artists.
How should I be doing this efficiently?
SELECT *
FROM table_updates
WHERE artist_id = 1
OR artist_id = 500
OR artist_id = 60032
Keep in mind, a user could have 43,000 of our artists marked as a favorite.
Thoughts?
This depends on how your database is setup. If I had my way, I'd set it up with a table like so:
Table: user_favourite_artist
user_id | artist_id
---------------------
1 | 2
1 | 8
1 | 13
2 | 2
3 | 6
6 | 20
6 | 1
6 | 3
user_id and artist_id together would be a composite primary key. Each row specifies a user, by id, and an artist they have as a favourite, by id. A query like so:
SELECT artist_id FROM user_favourite_artist WHERE user_id = 1
Would give you the artist_id's 2, 8, and 13. This is a very simple query that will scale to your expectations.
On the reverse, when an artist is updated, you'd run this query:
SELECT user_id FROM user_favourite_artist WHERE artist_id = 2
And you would get the user_id's 1 and 2. This will tell you which users to notify. This query is also simple and will scale.
Maybe you can try this:
SELECT *
FROM table_updates
WHERE artist_id IN(1, 500, 60032)
If you have the marked artists in a secondary table, I would recomend rather using a join.
Something like
SELECT *
FORM table_updates tu INNER JOIN
table_marked_by_user tmbu ON tu.artist_id = tmbu.artist_id
WHERE tmbu.user_id = $user_id
If you're on SQL Server, you can use a nested select statement:
select * from table_updates where artist_id in
(select artist_id from favorites_table where user_id = 10)
If you don't mind doing dirty reads, you can speed it up with (nolock).
select * from table_updates (nolock) where artist_id in
(select artist_id from favorites_table (nolock) where user_id = 10)