MySQL Extracting data from 3 tables - mysql

First of all apologies for the newbee question, I am totally new to MySQL.
I have 3 tables with some fields. The relevant fields for the query are as follows:
table 1 - Registration
user_name
user_email
ID
table 2 - photogallery
ID
user_id
Status
photo_url
table 3 - photovote
Photo_ID
status
I need a list of all the votes (1 record per vote) with explicited data of the photo and the user owning that photo. This means that Photo_ID in photovote is = to ID in photogallery and user_id in photogallery is = ID in Registration.
What I came up with is
SELECT *
FROM photovote
LEFT JOIN (photogallery, registration)
ON photovote.Status = 1
AND photogallery.Status = 1
WHERE photovote.user_id = photogallery.user_id
AND photogallery.user_id = registration.ID
But it really does'nt do the job. Anyone can point me to the right direction maybe?
Thanks a lot.
Andrea

SELECT *
FROM photovote v
INNER JOIN photogallery g ON v.PhotoId = g.ID
INNER JOIN registration r ON g.user_id = r.ID
WHERE v.Status = 1
AND g.Status = 1

SELECT r.user_name, r.user_email, p.status, p.photo_url, pv.status as pv_status FROM registration r LEFT JOIN photogallery p ON (r.id=p.id) LEFT JOIN photovote pv ON (pv.id=p.id) WHERE p.status = 1 AND pv_status = 1

Related

Can't SELECT records from two tables properly

I've been using this Query at first, Then used this Query at last
Which are
##Query[1]
SELECT t.title, p.content, p.version
FROM drafts d
INNER JOIN titles t ON t.id = d.tp_id AND d.t = 1
INNER JOIN posts p ON p.id = d.tp_id AND d.t = 2
WHERE user_id = 1
##Query[2]
SELECT coalesce(p.title, t.title), p.content, p.version
FROM drafts d
INNER JOIN titles t ON t.id = d.tp_id AND d.t = 1
INNER JOIN
(
SELECT pt.id, tp.title, pt.content, pt.version
FROM posts pt
INNER JOIN titles tp ON tp.id = pt.tid
) p ON p.id = d.tp_id AND d.t = 2
WHERE user_id = 1
What I want to do Using the Table: drafts to use
Column: tp_id as an identifier to the Column: id in other tables.
Column: user_id as the id of the user having the draft.
Column: t as the identifier to which table of Tables: titles[t=1], posts[t=2] to fetch the records from it.
In Table: posts the Column: tid links to the Column: id of Table: titles Which is used to pull the Column: title.
I want no records to be shown from the Table: titles if doesn't exist, And no records to be shown from the Table: posts if the title related using tid on Table: titles doesn't exist Or the record of the Table: posts doesn't exist, That why I used INNER JOIN.
But in both queries I don't get any results at all.
Is this even the proper table scheme and design to be used for something like the Drafts table for two different tables instead of one for each table?
The result I expect is something like this
title content version
TheTitle null null
TheTitle Content1 1
TheTitle Content2 2
TheTitle Content3 3
TheTitle Content4 4
TitleThe Content1 1
TitleThe Content2 2
TitleThe Content3 3
TitleThe Content4 4
A simple Example:
[table-a] [table-b]
[id - title ] [id - table_a_id - content ]
[1 - title-1] [1 - 1 - content-1]
table-a has the titles.
table-b has the content of each
title.
table-b column of table_a_id links the content with
the title of table-a.
[table-ab]
[user_id - table_col_id - table_letter]
[1 - 1 - a ]
[1 - 1 - b ]
table-ab has user_id to tell which user will be shown the records.
table-ab has table_letter to tell the query which table to fetch the data from it.
What I want the Query to do is to check table-ab and fetch the data from the other tables according to it, so it would be
table_letter = a => fetching rows from table-a.
table_col_id = 1 => fetching rows from table-a WHERE id = 1.
result = title-1
table_letter = b => fetching rows from table-b.
table_col_id = 1 => fetching rows from table-b WHERE id = 1.
result = title-1 - content-1
Final result:
id - title - content
-------------------------
1 - title-1 - null
2 - title-1 - content-1
Do two separate queries (for t=1 and t=2) and use UNION ALL to combine the results:
SELECT t.title, null content , null version
FROM drafts d
INNER JOIN titles t
ON t.id = d.tp_id
WHERE d.user_id = 1 and d.t = 1
UNION ALL
SELECT pt.title, pt.content, pt.version
FROM drafts d
INNER JOIN
( SELECT p.id, t.title, p.content, p.version
FROM posts p
INNER JOIN titles t ON t.id = p.tid ) pt
ON pt.id = d.tp_id AND d.t = 2
WHERE d.user_id = 1
As you are using inner join so please check the following:
Common data in both tables(joining column), if there will not be any common value it will not pick any thing.
Check data type of the column which are used to join both table that should be same if not then handle it
Extra spaces in the joining column.
After joining with condition d.t = 1 there is no data for d.t = 2 That's why after 2nd Join you are not getting any data. Try the below Query
SELECT coalesce(p.title, t.title), p.content, p.version
FROM drafts d
INNER JOIN titles t
ON t.id = d.tp_id
INNER JOIN
(
SELECT pt.id, tp.title, pt.content, pt.version
FROM posts pt
INNER JOIN titles tp
ON tp.id = pt.tid
) p
ON p.id = d.tp_id
WHERE user_id = 1
AND (d.t = 1 OR d.t = 2)
This will produce almost exactly what you have in your question. It does omit the line with the null values for the content and version. Not sure why that would have been in the expected output.
SELECT
if(d.t = 1,tp.title, if(d.t = 2,t.title,"")) as `title`,
p.content,
p.version
FROM drafts d
LEFT JOIN titles t ON t.id = d.tp_id AND d.t = 2
LEFT JOIN posts p ON t.id = p.tid
LEFT JOIN titles tp ON tp.id = p.tid AND d.t = 1
WHERE user_id = 1 AND NOT p.content IS NULL
I changed some of the data, specifically the groups of Content1 - Content4. I added "a" to the first 4, and "b" to the remainder.
Here's a SQL Fiddle that shows what it does.

How to select sql data by using 2 join tables with OR condition without duplicate records

I have a mysql select statement as below:-
select user.username, chat.from_user,chat.to_user,chat.message,chat.date_created
from chat join user on (chat.from_user or chat.to_user) in (user.user_id)
where(chat.from_user = 3 or chat.to_user = 3) and chat.chat_id IN
(SELECT distinct (MAX(chat.chat_id) )
FROM chat GROUP BY chat_group_id);
and here is my result
I always get username = admin. My expectation result is username will get correct from / to user.
Please help. Thank you.
SELECT
IF(chat.from_user=3, to_user
, IF(chat.to_user=3, form_user, 0)) AS username,
chat.from_user,chat.to_user,chat.message,chat.date_created
FROM chat
LEFT JOIN user fr_user ON chat.from_user = user.user_id
LEFT JOIN user to_user ON chat.to_user = user.user_id -- since you only want to show the TO_USERNAME, you can remove above line
WHERE (chat.from_user = 3 OR chat.to_user = 3) and chat.chat_id
IN
(SELECT distinct (MAX(chat.chat_id) )
FROM chat GROUP BY chat_group_id);
I think you intend:
select u.username, c.from_user, c.to_user, chat.message, c.date_created
from chat c join
user u
on u.user_id in (c.from_user, c.to_user)
where 3 in (c.from_user, c.to_user) and
c.chat_id in (select max(c2.chat_id)
from chat c2
group by chat_group_id
);

SQL query returns column with data from another column

I have a table Notices connected to tables Likes and Comments. When I return the notices for a user I also create columns: number_of_likes, number_of_comments and liked_by_me. The query is working correctly when the user making the query hasn't liked a notice (liked_by_me = 0) . But if they have (liked_by_me = 1) the value I get for number_of_likes is wrong and is the same as number_of_comments.
Example:
1)
- liked by me = false
- likes = 1
- comments = 5
Returned values:
- liked_by_me = 0
- number_of_likes = 1
- number_of_comments = 5
2)
- liked by me = true
- likes = 2
- comments = 5
Returned values:
- liked_by_me = 1
- number_of_likes = 5
- number_of_comments = 5
Here is the query I am using:
SELECT notices.*
, count(comment.id) as number_of_comments
, count(like1.user_id) as number_of_likes
, like2.user_id IS NOT NULL AS liked_by_me
, boards.name as board_name
FROM notices
LEFT JOIN comments as comment
ON (comment.notice_id = notices.id)
LEFT JOIN likes as like1
ON (like1.notice_id = notices.id)
LEFT JOIN likes as like2
ON (like2.notice_id = notices.id
AND like2.user_id = $1)
LEFT JOIN boards
ON (boards.id = notices.board_id)
LEFT OUTER JOIN board_users
ON (board_users.board_id = notices.board_id)
WHERE board_users.user_id = $1
GROUP BY notices.id
, boards.name
, like2.user_id
, userId
Any help would be appreciated. I have been on this for hours and I don't think I will be able to find the problem.
Thanks!
Solution:
Here is the working query
SELECT notices.*,
(SELECT COUNT(user_id) from likes WHERE likes.notice_id = notices.id) AS number_of_likes,
(SELECT user_id IS NOT NULL from likes WHERE likes.notice_id = notices.id AND likes.user_id = $1) AS liked_by_me,
count(comments.id) as number_of_comments, boards.name as board_name
FROM notices LEFT JOIN comments ON (comments.notice_id = notices.id)
LEFT JOIN boards ON (boards.id = notices.board_id)
LEFT OUTER JOIN board_users ON (board_users.board_id = notices.board_id)
WHERE board_users.user_id = $1 GROUP BY notices.id, boards.name", user);
You will have to use subeselects.
Excellent article on this problem: The GROUPing pitfall
TL;DR: Basically, you have to realize, that all your comments and likes are being multiplicated by one another. Try to display the result of the query without the group clause to see, that duplicate likes/comments are being counted.
EDIT: I didn't test this, but it's how the query might look:
(that is if user can only like one notice once, otherwise you would have to group current user likes too)
SELECT
notices.*,
comments.number_of_comments,
likes.number_of_likes
current_user_likes.user_id IS NOT NULL AS liked_by_me
boards.name AS board_name
FROM notices
LEFT JOIN (
SELECT
COUNT(*) AS number_of_comments,
notice_id
FROM comments
GROUP BY notice_id
) AS comments ON comments.notice_id = notices.id
LEFT JOIN (
SELECT
COUNT(*) AS number_of_likes,
notice_id
FROM likes
GROUP BY notice_id
) AS likes ON likes.notice_id = notices.id
LEFT JOIN likes AS current_user_likes
ON current_user_likes.notice_id = notices.id
AND current_user_likes.user_id = $1
LEFT JOIN boards ON boards.id = notices.board_id
INNER JOIN board_users
ON board_users.board_id = notices.board_id
AND board_users.user_id = $1;

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';

(My)SQL JOIN - get teams with exactly specified members

Assume tables
team: id, title
team_user: id_team, id_user
I'd like to select teams with just and only specified members. In this example I want team(s) where the only users are those with id 1 and 5, noone else. I came up with this SQL, but it seems to be a little overkill for such simple task.
SELECT team.*, COUNT(`team_user`.id_user) AS cnt
FROM `team`
JOIN `team_user` user0 ON `user0`.id_team = `team`.id AND `user0`.id_user = 1
JOIN `team_user` user1 ON `user1`.id_team = `team`.id AND `user1`.id_user = 5
JOIN `team_user` ON `team_user`.id_team = `team`.id
GROUP BY `team`.id
HAVING cnt = 2
EDIT: Thank you all for your help. If you want to actually try your ideas, you can use example database structure and data found here: http://down.lipe.cz/team_members.sql
How about
SELECT *
FROM team t
JOIN team_user tu ON (tu.id_team = t.id)
GROUP BY t.id
HAVING (SUM(tu.id_user IN (1,5)) = 2) AND (SUM(tu.id_user NOT IN (1,5)) = 0)
I'm assuming a unique index on team_user(id_team, id_user).
You can use
SELECT
DISTINCT id,
COUNT(tu.id_user) as cnt
FROM
team t
JOIN team_user tu ON ( tu.id_team = t.id )
GROUP BY
t.id
HAVING
count(tu.user_id) = count( CASE WHEN tu.user_id = 1 or tu.user_id = 5 THEN 1 ELSE 0 END )
AND cnt = 2
Not sure why you'd need the cnt = 2 condition, the query would get only those teams where all of users having the ID of either 1 or 5
Try This
SELECT team.*, COUNT(`team_user`.id_user) AS cnt FROM `team`
JOIN `team_user` ON `team_user`.id_team = `team`.id
where `team_user`.id_user IN (1,5)
GROUP BY `team`.id
HAVING cnt = 2