MySQL Query matching multiple fields - mysql

I have a database that has a table that has different LIKES that people have. Each like is stored as a different record. The only info I have in each record is userID, likeID.
The search will be based on the current userID that is signed in. So I'm not matching EVERYONE with EVERYONE but instead matching EVERYONE vs 1
So userID 45 might have likeID 3, likeID 6 and likeID 22 in the table (for instance)
What I want to do is have the table return, in descending order userIDs that they match with based on the total likes they match with someone else.
For example, (based on user 45 example above) it would look at userID 1 and see how many of likeID 3, likeID 6 and likeID 22 they have. then it'd go to userID 2 and see how many of likeID 3, likeID 6 and likeID 22 they have.....it'd do this for everyone.
Then it'd show the results for any that have more than 0 matches for those 3 likeIDs:
Matches:
You and UserID 12 share 3 of the same likes.
You and UserID 87 share 3 of the same likes.
You and UserID 22 share 2 of the same likes.
You and UserID 73 share 2 of the smae likes.
You and UserID 71 share 1 of the same likes.
etc...
I hope that explains what I'm trying to do. I don't think the mySQL query will be too hard but right now I'm baffled at how to do it!
THANKS IN ADVANCE!

select
UL2.userID,
count(*) as LikeMatches
from
UserLikes UL1
JOIN UserLikes UL2
on UL1.LikeID = UL2.LikeID
AND UL1.UserID != SingleUserBasisParameter
where
UL1.UserID = SingleUserBasisParameter
group by
UL2.UserID
order by
2 desc
The "2" in the order by is the ordinal column representing the COUNT(*)

select userid,count(*) as common_likes
from table
where likeid in (select likeid from table where userid = 45) and userid <> 45
group by userid
order by common_likes desc

how about:
SELECT COUNT(likes.likeID) as like_count FROM
LIKES as likes,
(SELECT UserID,likeID FROM likes WHERE UserID = $user_id) as user_likes
WHERE
user_likes.likeID = likes.likeID AND user_likes.userID != likes.userID
GROUP BY likes.UserID
ORDER BY like_count
I haven't tested it, but I think that it should at least give you the right idea. The 2nd SELECT finds all the likes of the main user, which you can then use to filter out the other likes.

Related

SQL - JOIN two tables and COUNT (also NULL values)

So I've got these three tables (it's a table tennis game):
table1: (goals, a user made, multiple rows)
id_goal
sp_id
game_id
time
table2: (users, multiple rows)
id_user
username
info_text
table3: (users_in_a_game, multiple rows)
id_uiag
game_id
sp_id
Now, I want to get all users from users_in_a_game, that played a game, want the name from users and the COUNT(goals) for every player, but the COUNT of the goals not in SUM, but for every single match in the specific row. So the result would be:
game1 - user1 - 50 goals
game1 - user2 - 20 goals
game2 - user3 - 12 goals
game2 - user1 - 7 goals
...
So far, I've coded this code:
SELECT *, COUNT(goals.sp_id) AS goals_per_game
FROM users_in_a_game
LEFT JOIN goals ON users_in_a_game.game_id = goals.game_id
GROUP BY goals.sp_id;
The problem is, that if a player was participating in the game, but doesn't score a goal, he doesn't get listed AT ALL. So how can I fix that?
Thank you in advance.
I think you want to aggregate by the user id and game id. I think:
SELECT ug.id_uiag, ug.game_id, COUNT(g.sp_id) AS goals_per_game
FROM users_in_a_game ug LEFT JOIN
goals g
ON ug.game_id = g.game_id
GROUP BY ug.id_uiag, ug.game_id;

How can you decide which records of a JOINED table remains after a GROUP BY?

I'm trying to LEFT JOIN two tables and GROUP BY a field of the first table in MySQL.
If there are multiple rows in the second table for each record in the first one, a GROUP BY eliminates all records but one of the right table. Is there a way to determine which one it is?
To give you a specific example, I want to get a list of users, joined with the IDs of their (for example) most expensive purchases (or most recent purchases, or whatever..) It seems like an easy task, but I'm frustrated and have asolutely no idea how to do it!
Table 1: Users
userId, userName
1 Frank
2 Sarah
3 Tim
Table 2: Purchases
orderId, userId, value
1 3 14.99
2 2 9.99
3 3 79.99
4 1 2.99
5 2 14.99
SELECT * FROM Users LEFT JOIN Purchases ON Users.userId = Purchases.userId
will return:
userId, userName, orderId, value
1 Frank 4 2.99
2 Sarah 2 9.99
2 Sarah 5 14.99
3 Tim 1 14.99
3 Tim 3 79.99
Now if I GROUP BY userId the result will be:
userId, userName, orderId, value
1 Frank 4 2.99
2 Sarah 2 9.99
3 Tim 1 14.99
Is there a way to decide in this case which orderId is kept or is there a completely other and better way to do this?
I have tried some things like MAX() but this will always only return the highest value of the whole table, not individually for each user.
Thank you in advance, you awesome stackoverflow-community!
best Florian
In strict SQL this Query would not be valid as in a Group by context u should select only fields contained in the group by clause or aggregates.
Mysql however allows this syntax and handles it as "i dont care about this fields", you can not define which of the rows values is selected then.
But you can do it with a query like this:
SELECT u.*,p.* FROM Users u LEFT JOIN
( SELECT userId, max(value) as max_value FROM Purchases GROUP BY userId) p ON u.userId = p.userId
If you want to get the max() pusrchase per user preserving the order like orderid etc you may need to do this
select
u.userId,
u.userName,
p.orderId,
p.value
from Users u
inner join Purchases p on
p.userId = u.userId
inner join
(
select orderId,
max(value) as value,
userId
from Purchases
group by userId
)o
on o.userId = p.userId
AND o.value = p.value
group by u.userId
http://sqlfiddle.com/#!2/1afda/9

My SQL Count( ) 0 with only 1 table

So I have seen this done with multiple tables, but am confused as to how this would work with multiple tables. I want to select the number of correct entries in a tournament. This works except if a user got none right. Then it returns NULL. I want this to return 0.
Table-tournament_entries
Column
=============
id
tournament_id
game_id
user_id
username
prediction
correct
Here is the query that I run, I am hoping to return all users even the ones who did not get any questions right.
SELECT
tournament_id, username, user_id, COUNT(`prediction`)
FROM
tournament_entries
WHERE
correct = 1 AND tournament_id = 1
GROUP BY
username
ORDER BY
COUNT(`prediction`) DESC
LIMIT 0,10
EDIT: Sorry for all the confusion so when I run my query I get this
username user_id CorrectAns
mj 455 10
charlie 1 8
bill 2 8
doug 51 7
but there are users who are not show who have received 0 right. When I run the queries suggested I receive the number of questions .
username user_id CorrectAns
mj 455 16
charlie 1 16
bill 2 16
doug 51 16
sydney 452 16
Joe 218 16
If you notice sydney and joe are not in the first output but are in the second one
Use this query:
$query ="SELECT tournament_id, username, user_id, COALESCE(COUNT(`prediction`),0) as cpred
FROM tournament_entries
WHERE tournament_id = 1
GROUP BY username
ORDER BY cpred DESC
LIMIT 0,10"
COALESCE will return the first non-null parameter given to it.
Cheers.
Based on your comments to the other answer, I think what you're actually looking for is something like this (although it's hard to be sure without sample data and output):
SELECT
username, user_id, Sum(correct) As TotalCorrect
FROM
tournament_entries
WHERE
tournament_id = 1
GROUP BY
username, user_id
ORDER BY
TotalCorrect DESC
LIMIT 0,10

mysql subquery issue on comments voting

I have MySQL query which I think needs a subquery. I'd like to count the total number of "up" votes on each of many comments and determine whether a given user has already voted on each comment:
Here are my tables:
Comments Table:
comment_id comment acct_id topic_id comment_date
5 hello5 2 1 9:00am
7 hello7 3 1 10:00am
Votes Table:
comment_id vote acct_id topic_id
5 1 1 1
7 1 4 1
5 1 5 1
here's the output i'm getting:
comment_id commenter comment voter sum did_i_vote
5 2 hello5 1 2 1
7 3 hello7 4 1 1
Here's the desired output:
comment_id commenter comment voter sum did_i_vote
5 2 hello5 **5** 2 1
7 3 hello7 4 1 1
Here's my query:
SELECT votes.acct_id as voter, comments.comment_id, comment, comments.acct_id as
commenter, SUM(vote) as sum, vote as did_i_vote
from votes
right join comments
on votes.comment_id=comments.comment_id
join accounts on comments.acct_id=accounts.acct_id
where topic_id=1
group by comments.comment_id order by comment_date desc
You'll notice these 2 outputs are identical except for voter.
What my query is missing is a way to determine whether a given user, for example with voter=acct_id=5, was the one who voted on any of the comments. Without that condition, the query picks the first voter in the list which for comment_id=5 is voter=1.
So my question is I think I need to insert the following subquery:
SELECT from votes where voter='X'
I'm just not sure where or how. Putting it in parentheses in between the from and votes above eliminates the sum() function so I'm stuck.
Any thoughts?
If I've understood you correctly from your comments above, I think all you need to do is (outer) join the votes table to your query another time, this time only on the votes of the account in question:
SELECT
comments.comment_id AS comment_id,
comments.acct_id AS commenter,
comment AS comment,
-- votes.acct_id AS voter, -- ambiguous
SUM(votes.vote) AS sum,
my_votes.vote IS NOT NULL AS did_i_vote
FROM
votes
RIGHT JOIN comments ON votes.comment_id=comments.comment_id
JOIN accounts ON comments.acct_id=accounts.acct_id -- what purpose ?
LEFT JOIN votes AS my_votes ON
my_votes.commentid=comments.comment_id
AND my_votes.acct_id=#my_acct_id
WHERE topic_id = 1 -- ambiguous
GROUP BY comments.comment_id
ORDER BY comment_date DESC

MYSQL sum of item purchases and its 'up'/'down' votes are multiplied by a factor of 22?

I'm trying to count the number of purchases and 'up'/'down' votes for all items that match a given search term. Unfortunately, as I've set up my query now, the purchases and vote counts are multiplied by a mysterious factor of 22 that I can not figure out where it comes from.
As an example for one of the items: the purchases, up, and down votes should be 7, 2, and 1 respectively but they are instead 154, 44, and 22.
here's my SQL code:
SELECT *
sum(purchaseyesno) as tots,
sum(rating=1) as yes,
sum(rating=0) as no
from items
join items_purchased
on items_purchased.item_id=items.item_id
join accounts
on items.account_id=accounts.account_id
like subject='%album by joe%' or description='%album by joe%'
group by item_id
order by tots desc, yes desc
Here's some sample data:
subject tots yes no full_name
album by joe 154 44 22 joe smith
album by fred 88 44 0 fred jones
Here's how i'd like the data to look:
subject tots yes no full_name
album by joe 7 2 1 joe smith
album by fred 4 2 0 fred jones
Would someone be able to help me figure out what is going on here? I can't figure out this factor of 22 issue which persists despite changing the group by and other things (meaning, this 22 number is independent of the # of returned rows).
You don't show your schema but it might help to use a subquery:
SELECT subject, tots, yes, no, fullnane
FROM (
SELECT item_id, SUM(purchaseyesno) AS tots, SUM(rating=1) AS yes, SUM(rating=0) AS no
FROM items_purchased
GROUP BY item_id
) i
JOIN items ON i.item_id = items.item_id
JOIN accounts ON items.account_id=accounts.account_id
WHERE subject LIKE '%album by joe%' OR description LIKE '%album by joe%'
ORDER BY tots DESC, yes DESC
Firstly, don't do select * if you're grouping by. Remember you must group by all non-aggregated fields.
Secondly, the high amount of results must be comming from those joins. Remove the group by and the aggregated columns and inspect the results and you'll see why you're getting so many records.
Finally... you're missing a where clause there...
SELECT subject,
sum(purchaseyesno)/22 as tots,
sum(CASE WHEN rating=1 THEN 1 END)/22 as yes,
sum(CASE WHEN rating=0 THEN 1 END)/22 as no,
full_name
from items
join items_purchased
on items_purchased.item_id=items.item_id
join accounts
on items.account_id=accounts.account_id
like subject='%album by joe%' or description='%album by joe%'
group by subject,full_name
order by tots desc, yes desc
In this query,the SUM function basically works on the columns purchaseyesno,rating=1,rating=0.
For eg.
Subject purchaseyesno rating full_name
1 5 1 Mark
1 6 0 Mark
2 7 1 Robert
2 8 0 Robert
The above query will return as below.
Subject tots yes no full_name
1 11 1 1 Mark
2 15 1 1 Robert