SQL to find users that the current user hasn't liked/disliked

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I have this really long query, which in my opinion looks ugly next to all the tidy code in my project. I was wondering if there was a way to optimize it or make it shorter at least:
$query = <<<SQL
SELECT * FROM users
WHERE NOT EXISTS (
SELECT id
FROM profile_likes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND NOT EXISTS (
SELECT id
FROM profile_dislikes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND id != $my_user->id
SQL
This query is a part of an user filter which has the purpose of filtering the users to only those that the currently logged in user ($my_user) hasn't liked/disliked yet.
performance php mysql
add a comment |Â
up vote
1
down vote
favorite
I have this really long query, which in my opinion looks ugly next to all the tidy code in my project. I was wondering if there was a way to optimize it or make it shorter at least:
$query = <<<SQL
SELECT * FROM users
WHERE NOT EXISTS (
SELECT id
FROM profile_likes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND NOT EXISTS (
SELECT id
FROM profile_dislikes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND id != $my_user->id
SQL
This query is a part of an user filter which has the purpose of filtering the users to only those that the currently logged in user ($my_user) hasn't liked/disliked yet.
performance php mysql
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
1
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
1
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to useUNIONand then do the sub-query, but someone may have a much better suggestion.
â Aluan Haddad
Feb 11 at 5:23
1
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have this really long query, which in my opinion looks ugly next to all the tidy code in my project. I was wondering if there was a way to optimize it or make it shorter at least:
$query = <<<SQL
SELECT * FROM users
WHERE NOT EXISTS (
SELECT id
FROM profile_likes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND NOT EXISTS (
SELECT id
FROM profile_dislikes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND id != $my_user->id
SQL
This query is a part of an user filter which has the purpose of filtering the users to only those that the currently logged in user ($my_user) hasn't liked/disliked yet.
performance php mysql
I have this really long query, which in my opinion looks ugly next to all the tidy code in my project. I was wondering if there was a way to optimize it or make it shorter at least:
$query = <<<SQL
SELECT * FROM users
WHERE NOT EXISTS (
SELECT id
FROM profile_likes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND NOT EXISTS (
SELECT id
FROM profile_dislikes
WHERE profile_id = users.id
AND viewer_id = $my_user->id
)
AND id != $my_user->id
SQL
This query is a part of an user filter which has the purpose of filtering the users to only those that the currently logged in user ($my_user) hasn't liked/disliked yet.
performance php mysql
edited Feb 11 at 5:10
Jamalâ¦
30.1k11114225
30.1k11114225
asked Feb 11 at 4:33
Ivan Grigorov
255
255
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
1
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
1
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to useUNIONand then do the sub-query, but someone may have a much better suggestion.
â Aluan Haddad
Feb 11 at 5:23
1
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59
add a comment |Â
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
1
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
1
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to useUNIONand then do the sub-query, but someone may have a much better suggestion.
â Aluan Haddad
Feb 11 at 5:23
1
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
1
1
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
1
1
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to use
UNION and then do the sub-query, but someone may have a much better suggestion.â Aluan Haddad
Feb 11 at 5:23
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to use
UNION and then do the sub-query, but someone may have a much better suggestion.â Aluan Haddad
Feb 11 at 5:23
1
1
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
Do you really need to keep likes and dislikes in different tables?
Seems to me that these would be pretty much the same thing with a different value in one single field. So maybe a profile_reactions table instead. Doing this would simplify your data model down to two tables and probably be more scalable in the future, if/when you want to ad more reaction types.
SELECT * should typically be avoided. It makes it harder for readers of the code to understand what fields they have to work with in the result set (they would have to go look at database schema to understand this). It can be more bandwidth intensive than necessary. It you only want a few fields from a table with a large number of fields, why pull all the extra data? It can potentially make the code more fragile. Can a database schema change potentially introduce bugs in code?
Consider whether relational storage (i.e. MySQL) is right for this in the long term. Since you are going to be dealing with most of the records in these tables, this is a query that really could be problematic over time, getting slower and slower as your user base grows. It simply doesn't scale well. The primary question to ask is whether the likes/dislikes (reactions) have any meaning outside the context of an owning user. My guess is that they don't. And if they don't, why does this data need to be normalized into it's own table?
This data model is one that actually works quite well in NoSQL storage, where the data model might look like this:
// User
"id": 123,
"reactions_to_users":
234: "like",
456: "dislike",
789: "like",
...
"reactions_from_users":
234: "like",
456: "dislike",
111: "like",
,
...
So assuming that you would already have this user object loaded up earlier in code (like you do know). When you go to make your query against the data store to get the the un-liked/disliked users, you would simply need to get the user ids under reactions_to_users and make a query against the data store for all users outside of this set.
I think your actual SQL code in PHP looks good. I prefer using heredoc or nowdoc syntax like you are doing. I also prefer SQL the read more vertically than horizontally, breaking up at each SQL phrase like you have done. I wouldn't change your style here.
add a comment |Â
up vote
3
down vote
Personally, I would just stick with what you have already got.
You could try something like this, although too me it doesn't look any tidier.
You would need to profile it against your database, to see if it performs any better.
SELECT *
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Do you really need to keep likes and dislikes in different tables?
Seems to me that these would be pretty much the same thing with a different value in one single field. So maybe a profile_reactions table instead. Doing this would simplify your data model down to two tables and probably be more scalable in the future, if/when you want to ad more reaction types.
SELECT * should typically be avoided. It makes it harder for readers of the code to understand what fields they have to work with in the result set (they would have to go look at database schema to understand this). It can be more bandwidth intensive than necessary. It you only want a few fields from a table with a large number of fields, why pull all the extra data? It can potentially make the code more fragile. Can a database schema change potentially introduce bugs in code?
Consider whether relational storage (i.e. MySQL) is right for this in the long term. Since you are going to be dealing with most of the records in these tables, this is a query that really could be problematic over time, getting slower and slower as your user base grows. It simply doesn't scale well. The primary question to ask is whether the likes/dislikes (reactions) have any meaning outside the context of an owning user. My guess is that they don't. And if they don't, why does this data need to be normalized into it's own table?
This data model is one that actually works quite well in NoSQL storage, where the data model might look like this:
// User
"id": 123,
"reactions_to_users":
234: "like",
456: "dislike",
789: "like",
...
"reactions_from_users":
234: "like",
456: "dislike",
111: "like",
,
...
So assuming that you would already have this user object loaded up earlier in code (like you do know). When you go to make your query against the data store to get the the un-liked/disliked users, you would simply need to get the user ids under reactions_to_users and make a query against the data store for all users outside of this set.
I think your actual SQL code in PHP looks good. I prefer using heredoc or nowdoc syntax like you are doing. I also prefer SQL the read more vertically than horizontally, breaking up at each SQL phrase like you have done. I wouldn't change your style here.
add a comment |Â
up vote
2
down vote
accepted
Do you really need to keep likes and dislikes in different tables?
Seems to me that these would be pretty much the same thing with a different value in one single field. So maybe a profile_reactions table instead. Doing this would simplify your data model down to two tables and probably be more scalable in the future, if/when you want to ad more reaction types.
SELECT * should typically be avoided. It makes it harder for readers of the code to understand what fields they have to work with in the result set (they would have to go look at database schema to understand this). It can be more bandwidth intensive than necessary. It you only want a few fields from a table with a large number of fields, why pull all the extra data? It can potentially make the code more fragile. Can a database schema change potentially introduce bugs in code?
Consider whether relational storage (i.e. MySQL) is right for this in the long term. Since you are going to be dealing with most of the records in these tables, this is a query that really could be problematic over time, getting slower and slower as your user base grows. It simply doesn't scale well. The primary question to ask is whether the likes/dislikes (reactions) have any meaning outside the context of an owning user. My guess is that they don't. And if they don't, why does this data need to be normalized into it's own table?
This data model is one that actually works quite well in NoSQL storage, where the data model might look like this:
// User
"id": 123,
"reactions_to_users":
234: "like",
456: "dislike",
789: "like",
...
"reactions_from_users":
234: "like",
456: "dislike",
111: "like",
,
...
So assuming that you would already have this user object loaded up earlier in code (like you do know). When you go to make your query against the data store to get the the un-liked/disliked users, you would simply need to get the user ids under reactions_to_users and make a query against the data store for all users outside of this set.
I think your actual SQL code in PHP looks good. I prefer using heredoc or nowdoc syntax like you are doing. I also prefer SQL the read more vertically than horizontally, breaking up at each SQL phrase like you have done. I wouldn't change your style here.
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Do you really need to keep likes and dislikes in different tables?
Seems to me that these would be pretty much the same thing with a different value in one single field. So maybe a profile_reactions table instead. Doing this would simplify your data model down to two tables and probably be more scalable in the future, if/when you want to ad more reaction types.
SELECT * should typically be avoided. It makes it harder for readers of the code to understand what fields they have to work with in the result set (they would have to go look at database schema to understand this). It can be more bandwidth intensive than necessary. It you only want a few fields from a table with a large number of fields, why pull all the extra data? It can potentially make the code more fragile. Can a database schema change potentially introduce bugs in code?
Consider whether relational storage (i.e. MySQL) is right for this in the long term. Since you are going to be dealing with most of the records in these tables, this is a query that really could be problematic over time, getting slower and slower as your user base grows. It simply doesn't scale well. The primary question to ask is whether the likes/dislikes (reactions) have any meaning outside the context of an owning user. My guess is that they don't. And if they don't, why does this data need to be normalized into it's own table?
This data model is one that actually works quite well in NoSQL storage, where the data model might look like this:
// User
"id": 123,
"reactions_to_users":
234: "like",
456: "dislike",
789: "like",
...
"reactions_from_users":
234: "like",
456: "dislike",
111: "like",
,
...
So assuming that you would already have this user object loaded up earlier in code (like you do know). When you go to make your query against the data store to get the the un-liked/disliked users, you would simply need to get the user ids under reactions_to_users and make a query against the data store for all users outside of this set.
I think your actual SQL code in PHP looks good. I prefer using heredoc or nowdoc syntax like you are doing. I also prefer SQL the read more vertically than horizontally, breaking up at each SQL phrase like you have done. I wouldn't change your style here.
Do you really need to keep likes and dislikes in different tables?
Seems to me that these would be pretty much the same thing with a different value in one single field. So maybe a profile_reactions table instead. Doing this would simplify your data model down to two tables and probably be more scalable in the future, if/when you want to ad more reaction types.
SELECT * should typically be avoided. It makes it harder for readers of the code to understand what fields they have to work with in the result set (they would have to go look at database schema to understand this). It can be more bandwidth intensive than necessary. It you only want a few fields from a table with a large number of fields, why pull all the extra data? It can potentially make the code more fragile. Can a database schema change potentially introduce bugs in code?
Consider whether relational storage (i.e. MySQL) is right for this in the long term. Since you are going to be dealing with most of the records in these tables, this is a query that really could be problematic over time, getting slower and slower as your user base grows. It simply doesn't scale well. The primary question to ask is whether the likes/dislikes (reactions) have any meaning outside the context of an owning user. My guess is that they don't. And if they don't, why does this data need to be normalized into it's own table?
This data model is one that actually works quite well in NoSQL storage, where the data model might look like this:
// User
"id": 123,
"reactions_to_users":
234: "like",
456: "dislike",
789: "like",
...
"reactions_from_users":
234: "like",
456: "dislike",
111: "like",
,
...
So assuming that you would already have this user object loaded up earlier in code (like you do know). When you go to make your query against the data store to get the the un-liked/disliked users, you would simply need to get the user ids under reactions_to_users and make a query against the data store for all users outside of this set.
I think your actual SQL code in PHP looks good. I prefer using heredoc or nowdoc syntax like you are doing. I also prefer SQL the read more vertically than horizontally, breaking up at each SQL phrase like you have done. I wouldn't change your style here.
answered Feb 11 at 17:26
Mike Brant
8,663619
8,663619
add a comment |Â
add a comment |Â
up vote
3
down vote
Personally, I would just stick with what you have already got.
You could try something like this, although too me it doesn't look any tidier.
You would need to profile it against your database, to see if it performs any better.
SELECT *
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null
add a comment |Â
up vote
3
down vote
Personally, I would just stick with what you have already got.
You could try something like this, although too me it doesn't look any tidier.
You would need to profile it against your database, to see if it performs any better.
SELECT *
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Personally, I would just stick with what you have already got.
You could try something like this, although too me it doesn't look any tidier.
You would need to profile it against your database, to see if it performs any better.
SELECT *
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null
Personally, I would just stick with what you have already got.
You could try something like this, although too me it doesn't look any tidier.
You would need to profile it against your database, to see if it performs any better.
SELECT *
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null
answered Feb 11 at 6:19
bumperbox
1,800614
1,800614
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187293%2fsql-to-find-users-that-the-current-user-hasnt-liked-disliked%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Be sure that those interpolated variables are not user input. If they could be, you need to use parameterization or you have no security.
â Aluan Haddad
Feb 11 at 4:51
1
None of the variables are user input.
â Ivan Grigorov
Feb 11 at 5:04
1
Roger, I was just checking, it's amazing how often people forget. Regarding your question, it seems MySQL is still crap and doesn't support many basic set operations. I think the best option is to use
UNIONand then do the sub-query, but someone may have a much better suggestion.â Aluan Haddad
Feb 11 at 5:23
1
I appreciate the concern. It happens to me quite often to forget to parametrize quries. I'll follow your suggestion and look into using UNION. Thanks.
â Ivan Grigorov
Feb 11 at 5:59