mysql database problem in fetching data from 4 tables? - mysql

tbl_users
tbl_questions
tbl_answares
tbl_questions_votes
SELECT
`tbl_users`.`email`,
`tbl_questions`.`q_id`,
`tbl_questions`.`question`,
`tbl_questions`.`tags`,
`tbl_questions`.`posted_at`,
SUM(tbl_questions_votes.upvote) AS upvotes,
SUM(tbl_questions_votes.downvote) AS downvotes
FROM
`tbl_users`
INNER JOIN
`tbl_answares`
ON
`tbl_answares`.`user_id` = `tbl_users`.`user_id`
LEFT JOIN
`tbl_questions`
ON
`tbl_questions`.`q_id` = `tbl_answares`.`q_id`
LEFT JOIN
`tbl_questions_votes`
ON
`tbl_questions`.`q_id` = `tbl_questions_votes`.`q_id`
WHERE
`tbl_users`.`user_status` = 1 AND `tbl_answares`.`user_id` = '6'
GROUP BY
`tbl_questions`.`q_id`
ORDER BY
`tbl_questions`.`posted_at`
DESC
Above query is returning email of user that answered the question (another columns are right output) but, i want the email of the user that asked the question.
output: output
Expected Output
`tbl_users`.`email`, // email of user that asked the question
`tbl_questions`.`q_id`,
`tbl_questions`.`question`,
`tbl_questions`.`tags`,
`tbl_questions`.`posted_at`,
SUM(tbl_questions_votes.upvote) AS upvotes,
SUM(tbl_questions_votes.downvote) AS downvotes

Try changing the INNER JOIN on tbl_questions_votes to a LEFT JOIN, since I'd assume it doesn't matter if a question has votes or not.
Secondly, you're joining the table answares and questions both on user_id. I don't think this makes too much sense, it seems to me that you're fetching users with the questions that they did and all the answares they submmited; while the expected output is the questions that this user has answared!
So, I think it would make more sense if you joined like this:
INNER JOIN
tbl_answares
ON
tbl_answares.user_id = tbl_users.user_id
INNER JOIN
tbl_questions
ON
tbl_questions.q_id = tbl_answares.q_id
LEFT JOIN
tbl_questions_votes
ON
tbl_questions.q_id = tbl_questions_votes.q_id
LEFT JOIN
tbl_users usrs2
ON
tbl_questions.user_id = usrs2.user_id
This joins a user with his answares along with the answares particular questions and the votes casted for those questions, without excluding questions that has no votes; and finnally joining with the users that made each question you are retrieving.
If you have any doubts around joining tables in SQL, I recommend this great SO topic and this other one

Related

how do i join third table values into main join?

in query here i have https://www.db-fiddle.com/f/32Kc3QisUEwmSM8EmULpgd/1
SELECT p.prank, d.dare
FROM dares d
INNER JOIN pranks p ON p.id = d.prank_id
WHERE d.condo_id = 1;
i have one condo with id 1 and it have unique connection to dares that has connection to pranks and unique connection to condos_pranks
and i wanna have all unique pranks from both tables and i used this query above to get relation of
dares to pranks and expected result was L,M,N - Yes,No,Maybe and it is correct but i also wanna have those in condos_pranks which ids are 1,4,5,6 = L,O,P,Q
so i tried to join the table with left join because it might not have condos_pranks row
SELECT p.prank, d.dare
FROM dares d
INNER JOIN pranks p ON p.id = d.prank_id
LEFT JOIN condos_pranks pd ON pd.condo_id = d.condo_id AND pd.prank_id = p.id
WHERE d.condo_id = 1;
but result is same as first and what i want is
prank
dare
L
Yes
M
No
N
Maybe
O
No
P
No
Q
No
with default being No = 2 if prank_id of condos_pranks is not in dares
how to connect it?
This seems like an exercise in identifying extraneous information more than anything. You are unable to join something to a table that has no key, however if you know your default then you may use something like coalesce to identify the records where there was no data to join NULL and replace them with your default.
I mentioned in a comment above that this table schema makes little sense. You have keys all over the place that doing have all sorts of circular references. If this is your derived schema, consider stopping here and revisiting the relationships. If it is not and it is something educational, which I suspect it is, disregard and recognize the logical flaws in what you are working in. Perhaps consider taking the data provided and creating a new table schema that is more normalized and uses other tables to handle the many to many and one to many relationships.
dbfiddle
SELECT
pranks.prank,
COALESCE(dares.dare, 'No')
FROM pranks LEFT OUTER JOIN
dares ON pranks.id = dares.prank_id
ORDER BY pranks.prank ASC;
clearlyclueless gave correct explanations
To achieve the result, the following SELECT can also be used:
SELECT
pranks.prank,
case
when dare is null then 'No'
else dare
end
FROM pranks LEFT OUTER JOIN
dares ON pranks.id = dares.prank_id

How to count rows in table with condition WHERE?

There is a query that to count rows from table question_category:
SELECT
idSpecialization,
thematicspecialization.SpecializationName AS SpecializationName,
SubscrubeToUsersIdNote,
COUNT(question_categoryId) AS CNT,
COUNT(idSubscrubeToUsers) AS SUBS
FROM thematicspecialization
LEFT JOIN question_category ON question_category.question_categoryIdCategory = thematicspecialization.idSpecialization
LEFT JOIN question a ON a.idQuestion = question_category.question_categoryIdQuestion
LEFT JOIN subscrubetousers ON (subscrubetousers.SubscrubeToUsersIdNote = idSpecialization AND subscrubetousers.SubscrubeToUsersType = 4 AND SubscrubeToUsersStatus = 1)
WHERE a.country = 1
GROUP BY idSpecialization
Need display the category names of thematicspecialization with the condition WHERE a.country = 1 for joining tables question a ON a.idQuestion = question_category.question_categoryIdQuestion
In my case - the categories are not displayed.
This is too long for a ocmment.
This is your query, fixed up a bit to use table aliases so it is easier to read:
SELECT ts.idSpecialization, ts.SpecializationName, sts.SubscrubeToUsersIdNote,
COUNT(question_categoryId) AS CNT,
COUNT(idSubscrubeToUsers) AS SUBS
FROM thematicspecialization ts LEFT JOIn
question_category qc
ON qc.question_categoryIdCategory = ts.idSpecialization LEFT JOIN
question q
ON q.idQuestion = qc.question_categoryIdQuestion LEFT JOIN
subscrubetousers sts
ON (sts.SubscrubeToUsersIdNote = ts.idSpecialization AND
sts.SubscrubeToUsersType = 4 AND
sts.SubscrubeToUsersStatus = 1)
WHERE q.country = 1
GROUP BY idSpecialization;
Here are things that I notice:
The join between ts and qc is on IdCategory and idSpecialization. That seems like a strange combination of names.
The join between sts and ts is partly on SubscrubeToUsersIdNote and idSpecialization. That seems like a strange combination of names.
The where condition is turning some left joins into inner joins -- calling into question why you want left join anyway.
The two count columns are going to return very similar numbers, because they are counting non-NULL values on join keys`.
Your question is about "categories" and their "names". However, based on your query, it is entirely unclear what fields these refer to.
Based on this query, I have no idea what you are really trying to do. You should probably write another question, with sample data and desired output to express what you are trying to do. This question already has two answers. Clarifying it so it would be understood would (probably) invalidate the answers, which is impolite.
Not clear.
But I guess. You have a join with condition like
subscrubetousers.SubscrubeToUsersIdNote = idSpecialization AND subscrubetousers.SubscrubeToUsersType = 4 AND SubscrubeToUsersStatus = 1be this
May be this condition conflict thematicspecialization field

Retrieve matching data twice from same LEFT JOIN table?

Information
Is there a way that I can retrieve two bits of information from another(same) table twice in one LEFT JOIN?
Attempt
Below is the SQL query I tried to put together in hopes would work. I hope you can see what I am trying to do from it.
SELECT cards.*, list.name FROM cards
LEFT JOIN list ON cards.main = list.id AS main_name
AND cards.enemy = list.id AS enemy_name
WHERE cards.id = 1
As you can see above I am trying to retrieve the names of two values cards.main AND cards.enemy from the list table.
Thank you, and any questions will be answered asap!
You have to join the list-table twice:
SELECT cards.*, main_name.name, enemy_name.name
FROM cards
LEFT JOIN list AS main_name ON cards.main = main_name.id
LEFT JOIN list AS enemy_name ON cards.enemy = enemy_name.id
WHERE cards.id = 1

SQL JOIN a table and GROUP BY to get correct row

Here is the situation, i for the tables forum_topics, forum_replies and users.
Where the _topics contains all the topics, the _replies contains all posts and the users contain all users.
I'm trying to list the topics as:
(Subject)__________________________________(Time of last reply)
(Topic created by username)__________________(Last reply by)
For now, the "subject" and "topic created by username" displays just fine, however, the time of the last post and user who posted it is wrong.
SQL:
SELECT
forum_topics.id,
forum_topics.category,
forum_topics.subject,
forum_topics.created AS topiccreate,
forum_topics.createdby AS topiccreatedby,
forum_replies.topic,
forum_replies.created AS repliecreated,
forum_replies.createdby AS repliecreatedby,
usertopic.firstname AS topicfirstname,
usertopic.lastname AS topiclastname,
userreplie.firstname AS repliefirstname,
userreplie.lastname AS replielastname,
usertopic.id as topicid,
userreplie.id
FROM forum_topics
JOIN forum_replies ON forum_replies.topic = forum_topics.id
JOIN users usertopic ON forum_topics.createdby = usertopic.id
JOIN users userreplie ON forum_replies.createdby = userreplie.id
WHERE forum_topics.category = '1'
GROUP BY forum_replies.topic
ORDER BY forum_replies.created DESC
How can i get the "Time of last reply" and "Last reply by" to display correct? I've tried removing the Group By, and then it retrieves all the posts, however i just want the very latest post-data for each topic.
As for now when using GROUP BY, it retrieves all the topics just once (correct) but the last reply by and time of the last reply is not displaying correct as it seems to retrieve the data for the first post of each topic.
Hope you understand my question! :/
You need one more condition to get the latest reply. Here is how you would do it in the join clause:
FROM forum_topics
JOIN forum_replies ON forum_replies.topic = forum_topics.id
JOIN users usertopic ON forum_topics.createdby = usertopic.id
JOIN users userreplie ON forum_replies.createdby = userreplie.id
JOIN (select topic, max(created) as maxcreated
from forum_replies
group by topic
) frmax on frmax.topic = forum_replies.topic and
frmax.maxcreated = forum_replies.created;
I don't think you will need the group by after doing this.
Try removing both group by and order by in your SQL query and check.

php mysql join 3 tables

Im looping through a feedback type comment system on a users page, finding the latest 6 posts.
To display the post how I want, I have to grab data from 3 tables.
I figure it'd be less db intensive if it was all pulled in one query, but I'm not sure how to write it, being suck at JOINs and things.
This is my existing code
$sql_result = mysql_query("SELECT * FROM feedback WHERE user='1' ORDER BY date desc LIMIT 6", $db);
while($rs = mysql_fetch_array($sql_result)) {
$sql_result2 = mysql_query("SELECT * FROM members WHERE id= '$rs[author]'", $db);
$rs2 = mysql_fetch_array($sql_result2);
if ($rs2[clan] != 0) {
$sql_result3 = mysql_query("SELECT * FROM clans WHERE id= '$rs2[clan]' LIMIT 1", $db);
$rs3 = mysql_fetch_array($sql_result3);
// write comment
Can someone give me a clue?
This should do it:
select * from feedback
left join members on feedback.author = members.id
left join clans on members.clan = clans.id
where feedback.user = 1
left join means if the table on the right has no matching row, a record with all null values is returned, so you still get the data from the table on the left.
I am no expert in Sql myself, but I have picked up a few tricks here and there :-)
A typical LEFT JOIN that works in Firebird is :
select A.*,B.*,C.*
from FEEDBACK A left join MEMBERS B
on A.USER = B.ID left join CLANS C
ON C.ID = A.USER
where A.USER=1
The logic behind the join is that All rows that now share the same value,
A.USER = B.ID = C.ID will now be visible.
The letters A B and C is just used for simplicity.
F, M and C will work the same way.
This Left Join will pick out all and every column in tables. This is done with A.*,B.*,C.*
Maybe you want only a few columns in each table.
That can be accomplished by naming the columns in the same manner.
Example:
A.USER,A.FIRSTNAME,A.SURNAME,B.COLNAME1,B.COLNAME2,C.COLNAME1,C.COLNAME2
When you need to adress the columns later, remember the Prefix of A. or B. or C. before the actual column-name you address.
Good luck and best regards.
Morten, Norway