MySQL three table join, find item's rating - mysql

I'm hoping this is an easy one for you gurus, but my SQL knowledge is failing me.
My sample dataset:
item
----
item_id item_name item_added
1 Apple <date_time>
2 Banana <date_time>
user
----
user_id user_name
1 Alice
2 Bob
3 Carol
rating
------
rating_id item_id user_id rating_value
1 1 1 3
2 1 2 4
3 1 3 5
4 2 1 5
5 2 2 2
I want to find out what rating all three users have given to a particular item. The output should include NULL for rating_value if the user hasn't rated the item. For example, if I have item_id 2, I'd like to get this output:
user_name item_name rating_value
Alice Banana 5
Bob Banana 2
Carol Banana NULL
I've tried all kinds of joins, but I just can't seem to figure this one out.
Many thanks in advance.

It looks like you want a cartesian product of user and item, which will then be joined with rating:
select user_name, item_name, rating_value
from user as u, item as i
left join rating as r
on r.user_id = u.user_id
and r.item_id = i.item_id
I haven't done any serious work with MySQL for 4.5 years, but this should do it.
Edit: Maybe MySQL requires AS for the table aliases.

select u.user_name, i.item_name, r.rating_value
from item i,user u
left join rating r
on r.user_id = u.user_id
and r.item_id = i.item_id
This should do the trick..

Related

Mysql trigger that multiplies two values from different tables, totalizes by groups and adds values to another column

I've been going around this for a while and there isno way I can figure it out. Let's say I have these three tables:
Users
Name | Basket value
-------+---------------
John | ???
-------+---------------
Pierre | ???
Items
User | Item | Amount
-----------+------------+------------
John | Pears | 2
-----------+------------+------------
Pierre | Pears | 1
-----------+------------+------------
Pierre | Apples | 3
Market_ prices
Item | Price
------------+---------------
Pears | 2.35
------------+---------------
Apples | 2.56
Basket value is needed. So for each row in ITEMS it must multiply its AMOUNT by MARKET_PRICES[PRICE] and sum all the results grouped by USER and place this result in USERS[total items value]. But how could the syntax be elaborated to take this to practice?
Many thanks in advance for the help.
One approach is to join the relevant tables:
SELECT u.name, SUM(i.amount*m.price)
FROM users u
JOIN items i ON u.name = i.user
JOIN market_prices m ON i.item = m.item
GROUP BY u.name;
(SQLfiddle of this is at: http://sqlfiddle.com/#!9/ec224/6 - I added a few other rows to the tables to test more complexity, so the totals aren't what you'd get from your example. Specifically, I added Bananas 3.75 to the Market_prices table and John Apples 3 and Pierre Bananas 5 to the Items table.)
The goal here is to link the information in all three tables through shared fields (via the JOIN), while also GROUPing and creating a SUM of the calculated costs as a product of market price and number of items.
---- edited based on comments ----
To do this as an update, you could try:
UPDATE users
SET basket_value = (SELECT basket FROM
(SELECT name, SUM(i.amount*m.price) AS basket
FROM users u JOIN items i ON u.name = i.username
JOIN market_prices m ON i.item = m.item
GROUP BY u.name) q1 WHERE q1.name = users.name);
I have a feeling there is a more elegant solution, but this works. Modified SQLFiddle is: http://sqlfiddle.com/#!9/56245a/1
SELECT User, SUM(rev) AS basket_price
FROM
(
SELECT a.User AS User, a.Amount*b.Price AS rev
FROM Items a
LEFT JOIN
Market_Prices b
ON a.Item = b.Item
) a1
GROUP BY User

I want to fetch data from 2 different table

I want to fetch result master.category wise suppose if i have
$category ='doctor'
then how can i get the result? i have drawn the tables below and expected result also, Please help me. thanks
table name->Master
------------------
id label category
1 expertise doctor
2 fee doctor
3 appontment doctor
4 services lawyer
5 qualification student
table name->Field
------------------
id label_id Information
1 1 desntist
2 1 general_physician
3 1 general_surgeons
4 4 criminal_law
5 5 civil_law
expected result
--------------------
expertise
dentist
general_physician
general_surgeons
Perform a JOIN like
select f.information as 'expertise'
from field f
join master m on m.id = f.label_id
where m.category = 'doctor';
its query give all information by master's id
SELECT m.label, GROUP_CONCAT(Information)
FROM Master m
JOIN Field f
ON m.id = f.label_id
WHERE m.category = 'doctor'

Counting votes and if user voted in MySQL table

I have 3 MySQL tables:
Features table:
id name
----------
1 feature 1
2 feature 2
3 feature 3
4 feature 4
5 feature 5
Votes table:
userid featureid
----------------
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
4 1
Users table:
id name
--------
1 John
2 Alice
3 Bob
4 Mark
5 Jane
6 Mary
7 Ann
I need to fetch in single query:
always all features, regardless if they have votes or not
each feature must be listed only once regardless of number of votes even if it has no votes
votes count for each feature listed
a special mark if currently logged user voted for current feature in the list - for example if user 3 is logged in, then list all features with votes count for all users and if user 3 voted for some features have a special field indicating his vote or NULL if he didn't (other data from votes table must be included too so it needs to be LEFT JOINED)
So far I did this:
SELECT *,(SELECT COUNT(*) FROM votes WHERE votes.featureid=features.id) AS "votecnt"
FROM features
LEFT JOIN votes ON votes.featureid=features.id
LEFT JOIN users ON users.id=votes.userid
GROUP BY features.id
It lists all features but has no special field if user 3 voted. I tried with IF, various WHERE conditions and after a lot of tries... ran out of ideas.
Desired output might look like this:
features.id features.name votes.userid votes.otherfields users.id users.name
1 feature 1 4 - 4 Mark
2 feature 2 NULL - NULL NULL
3 feature 3 NULL - NULL NULL
4 feature 4 NULL - NULL NULL
5 feature 5 NULL - NULL NULL
All the features are listed and only those where user 4 voted have other joined tables filled, others are simply NULL. If someone else voted for feature 2 it is still NULL as it is of no relevance for user 4 because in this example user 4 is logged in.
Here is the problem:
http://sqlfiddle.com/#!2/c3d10/3
http://sqlfiddle.com/#!2/c3d10/4
http://sqlfiddle.com/#!2/c3d10/5
http://sqlfiddle.com/#!2/c3d10/6
http://sqlfiddle.com/#!2/c3d10/7
All of above queries in SQLFiddle it should output all 5 features regardless of the userid. So the query must be modified somehow to show all features - even if other people voted for a feature or if there are no votes or if current user voted for feature.
this should do it:
SELECT tmp1.id, name, votecnt, user_id, user_name FROM
(SELECT *,(SELECT COUNT(*) FROM votes WHERE votes.featureid=features.id) AS "votecnt" FROM features) as tmp1
LEFT JOIN (SELECT features.id as feature_id, users.id as user_id, users.name as user_name FROM features
JOIN votes ON votes.featureid=features.id
JOIN users ON users.id=votes.userid
WHERE users.id=3) as tmp2 on tmp1.id = tmp2.feature_id
probably it's not the prettiest sql, and most likely there's also room for optimization
I think you're asking to have all features returned, all counts returned, but only user information if they voted for that feature.
I get the results you're looking for if you specify the userid
select f.id
, f.name
, u.id
, u.name
, v.votecnt
from features f
left join (select featureid, COUNT(userid) votecnt from votes group by featureid) v on v.featureid = f.id
left join votes v1 on v1.featureid = f.id and v1.userid = 4
left join users u on u.id = v1.userid
I chose to specify the userid inside the left join to the votes. Anywhere else and it limits the total number of rows returned.
Results:
1 feature 1 4 Mark 4
2 feature 2 NULL NULL 3
3 feature 3 NULL NULL 3
4 feature 4 NULL NULL 2
5 feature 5 NULL NULL NULL
Example with "Bob"
select f.id
, f.name
, u.id
, u.name
, v.votecnt
from features f
left join (select featureid, COUNT(userid) votecnt from votes group by featureid)v on v.featureid = f.id
left join votes v1 on v1.featureid = f.id and v1.userid = 3
left join users u on u.id = v1.userid
Results:
1 feature 1 3 Bob 4
2 feature 2 3 Bob 3
3 feature 3 3 Bob 3
4 feature 4 NULL NULL 2
5 feature 5 NULL NULL NULL

Query with GROUP_CONCAT not working

I have 3 tables with the following structure:
**users**
id
first_name
last_name
**specialties**
specialty_id
specialty_name
**user_specialties**
user_id
specialty_id
Here is some sample data:
**users**
1 Bill Smith
2 Tom Jones
3 Jill Hayes
**specialties**
1 word
2 web
3 database
**user_specialties**
1 1
2 1
2 3
3 2
3 3
I need to query the data so the specialties are concatinated on one row like the below output
**Desired Result**
Bill Smith word
Tom Jones word,database
Jill Hayes web,database
I am using the following query
SELECT
users.first_name,
users.last_name,
GROUP_CONCAT(specialties.specialtyname)
FROM
users
LEFT JOIN user_specialties ON user_specialties.user_id = users.userid
RIGHT JOIN specialties ON user_specialties.specialty_id = specialties.specialty_id
It is not working...
You're missing a GROUP BY clause. Most likely it should be GROUP BY users.id, and it'd go AFTER the JOIN lines.
I just tested this query
SELECT first_name,last_name,group_concat(specialty_name)
FROM user_specialties map
INNER JOIN specialties skill on user.id = map.user_id
INNER JOIN users user ON skill.specialty_id = map.specialty_id
GROUP BY user.id
Cheers! :-)

Join, Group By and Sum in MySQL

I have the following three tables in a MySQL database in order to give ratings to comments of users:
Users:
id name
-----------
1 Smith
2 Brown
Comments:
id user_id post_id comment
-----------------------------------
1 2 1 Test 1
2 1 1 Test 2
3 1 1 Test 3
Scores:
id user_id comment_id score
------------------------------------
1 1 1 1
Now I want to select all the comments for post_id = 1, plus the username and the sum of all the scores on that specific comment. At first it looks very simple, I came up with this query:
SELECT users.name, comments.comment, SUM(scores.score) AS score
FROM comments
LEFT JOIN users ON users.id = comments.user_id
LEFT JOIN scores ON scores.comment_id = comments.id
WHERE comments.post_id = 1
GROUP BY scores.comment_id
It seems to work, but when there isn't a score for a specific comment, the comment doesn't show up, because MySQL can't GROUP BY NULL, I guess. So, is there any way to include those unrated comments? Like this:
Query result:
name comment score
-------------------------
Brown Test 1 1
Smith Test 2 0
Smith Test 3 0
You could try grouping on comments.id instead perhaps?