Select rows and display as columns from mySQL database - php

All,
I've got the following mySQL table structure:
Table dj_feedback_answers: answer_id, gig_id, question_id, answer_id
Table dj_feedback_summary: summary_id, user_id, gig_date, tip, summary, why_poor, why_fair
Table dj_feedback_questions: question_id, question_value, question_display
Table dj_feedback_ratings: rating_id, rating_value, rating_display
I'm basically asking users questions and the questions are stored in the dj_feedback_questions table and allowing them to give a rating for each question. The ratings are stored in the dj_feedback_ratings.
Each form can having variable questions so when I submit the questions I store the answers in the dj_feedback_answers. There are other more static fields on the form and those get svaed into the dj_feedback_summary. The summary_id and the gig_id are the keys that connect the two tables for the answers that the user submitted.
This means that there can be multiple rows in the dj_feedback_answers for a single row in the dj_feedback_summary table.
What I would like to do is basically be able to utilize the results in a PHP table. So I'd like my results to look something like this (assuming there are three questions in the dj_feedback_questions table):
summary_id, user_id, gig_date, tip, summary, why_poor, why_fair, question_1, question_2, question_3
1, 2, 07/23/2012, 5, This is a summary, It was poor, It was fair, 3, 4, 5
The values that would be stored for the questions would be the answer_id from the dj_feedback_answers.
I tried to create the following query to get my results. This works ok but it only can display a single question instead of all of the questions.
Select dj_feedback_summary.summary_id,
dj_feedback_summary.user_id,
dj_feedback_summary.gig_date,
dj_feedback_summary.tip,
dj_feedback_summary.summary,
dj_feedback_answers.question_id,
dj_feedback_answers.rating_id,
dj_feedback_questions.question_value,
users.first_name, users.last_name,
dj_feedback_ratings.rating_value
from dj_feedback_summary
join dj_feedback_answers on dj_feedback_summary.summary_id=dj_feedback_answers.gig_id
join dj_feedback_questions on dj_feedback_answers.question_id=dj_feedback_questions.question_id
join users on dj_feedback_summary.user_id=users.user_id
join dj_feedback_ratings on dj_feedback_ratings.rating_id=dj_feedback_answers.rating_id
where dj_feedback_questions.question_value='Overall Gig'
order by dj_feedback_summary.summary_id DESC
Is there a way to modify my query so it can return my results how I would like them?
Any advice is greatly appreciated!
Thanks

If you need values from multiple rows displayed, and it's not essential that they be in separate columns, then the MySQL GROUP CONCAT function would probably suit your purposes.
That would give you question_1, question_2, and question_3 values concatenated into a single column (if I understand your output intent correctly).
Update: To do a more "genuine" pivot (separating the answers to different questions into different columns), you could use one of the following approaches:
1) Use multiple table aliases: join to the dj_feedback_questions table one time for each question, e.g. something along these lines:
SELECT [...] FROM [...]
LEFT JOIN dj_feedback_questions q1 on q1.question_id = 1
LEFT JOIN dj_feedback_questions q2 on q2.question_id = 2
LEFT JOIN dj_feedback_questions q3 on q2.question_id = 3
You will then need to a) join to dj_feedback_answers similarly (multiple times with aliases), since you get to it via question_id, and you want different questions separated into different columns, and b) aggregate the results and decide how you want to handle nulls, since doing a regular JOIN instead of a LEFT JOIN will cause you to lose the row for any summary that lacks an answer to one or more questions.
2) Break into columns with an IF block: See this SO question (specifically the accepted answer) for an illustration: Transpose mysql query rows into columns

Related

Join tables when fields aren't equal - PHP MySQL

I created two tables, one stores the questions of a quiz, and the other one stores all the answers, that users made.
The first table called "questions" contains the questions:
Field names: id|question
Eg. contents:
1|what's your fav color?
2|what's your fav animal?
The second table named "answers" stores all the answers, that users made:
Fields names: id|questionid|userid|answer
Eg. contents:
1|1|1|Red
1|1|3|Magenta
1|1|4|Green
I'd like to select those questions, that haven't been answered yet by a user.
I store the current user's id in a $_SESSION['id'] session. I tried so many ways, to get these questions, the closest query I've made, was this:
$query = SELECT questions.*, answers.* FROM questions LEFT JOIN answers ON questions.id=answers.questionid WHERE answers.id IS NULL OR answers.userid <> '.$_SESSION['id'];
This won't work, because if there's another userid in the answers table at the same question id, it still selects that row. What could be the problem? Where did I mess up my query?
Thanks in advance for all of your help!
Your user condition is in the wrong place. Since you'll want to try to find a match between the specific user and the question and detect a non match, the user part needs to go inside the ON clause with a null check in the WHERE clause;
SELECT q.*
FROM questions q
LEFT JOIN answers a
ON q.id = a.questionid
AND a.userid = YOUR_USER_ID
WHERE a.id IS NULL
An SQLfiddle to test with.

Multiple table select grouped query

We need to grab the last and newest 20 entries from different tables. However, the GROUP BY statement skips records because we are working with LEFT JOIN on tables.
All these records are linked to unique persons in another table. We store these person's id's in an array for more queries later.
We have a few tables (in which all those person id's are stored) and we want to get them sorted and grouped.
The tables are like this:
SELECT lastRecord+personID FROM t1
SELECT lastRecord+personID FROM t2
SELECT lastRecord+personID FROM t3
SELECT lastRecord+personID FROM t4
WHERE t5.Essential_Column_Name = '1'
GROUP BY personID
ORDER BY 'all the latest entries'
LIMIT 20
With that, the relevance of all the latest entries should be equal.
We do have a timestamp column as well. Perhaps that might work better.
Any input is highly appreciated!
For people looking for an answer on this; this is the right post, answer and update to this Q:
UNION mysql gives weird numbered results
With thanks to all for the ideas and providing the paths to the right solution.

select from mulitiple tables and then join

I'm new here and I hope I am asking my question correctly:
I am trying to implement search on forums database.
I have 'questions' table and 'answers' table (they both related by 'id_question' field). I also have 'suggestions' table and 'comments' table that are also related.
In addition I have 'profiles' table which related to every table I've mentioned before by 'profile_id' field, this profiles table holds the information on the users.
I would like to implement wide search on specific fields ('topic', 'description'...) in all the four tables I've mentioned before, and display those fields and the information of the user who wrote the post.
I really messed with this.
right now I have 4 queries (for each table), and each query makes join with profiles table.
Do you know better way to do this?
Thanks!
You can do this with INNER JOINS. I recommend starting with some simple INNER JOINS and building up your queries to be more inclusive and join more tables. It all depends on what you're trying to get, really. Be as precise as possible in returning exactly the information you want.
Here is a simple example and the assumptions I made:
Assuming the following
table: primarykey*, foreignkey#, othercolumns
questions: id_questions*, topic, description, profile_id#
answers: id_answers*, id_questions#, topic, description, profile_id#
suggestions: id_suggestions*, topic, description, profile_id#
comments: id_comments*, topic, description, profile_id#
user: profile_id*, name, details
KEYWORD: replace with your keyword or phrase
Look for a keyword in the questions and answers
SELECT * FROM questions q
INNER JOIN answers a
ON q.profile_id = a.profile_id
WHERE topic LIKE '%KEYWORD%'
OR description LIKE '%KEYWORD%';
Get the user profile for a user who used keyword in the questions and answers tables:
SELECT u.* FROM users u
INNER JOIN answers a
ON u.profile_id = a.profile_id
INNER JOIN questions q
ON q.profile_id = u.profile_id
WHERE topic LIKE '%KEYWORD%'
OR description LIKE '%KEYWORD%';
Hope this helps.
Edit: formatting.
Yes, do it in four queries.
Otherwise you will get a Cartesian product as you try to join the tables.
I think you can try using UNION. Is not it?

How to select from / join 5 tables using PHP and mySQL

I'm trying to build a review record based on fields from 5 tables:
I've marked all the columns I need, but for the moment I'm just retrieving all of the user_rating table.
Here's what I have so far:
SELECT DISTINCT user_rating.*, whiskey.name, user_notes.overall, users.image, user_rate.rate_number
FROM user_rating
LEFT JOIN whiskey ON whiskey.id = user_rating.whiskeyid
LEFT JOIN users ON users.username = user_rating.username
LEFT JOIN user_notes ON user_notes.username = user_rating.username AND user_rating.whiskeyid = user_notes.whiskey_id
LEFT JOIN user_rate ON user_rate.whiskey_id = user_rating.whiskeyid AND user_rate.username = user_rating.username
ORDER BY user_rating.id DESC
At first I thought this was giving me the results I wanted but then I noticed I was getting multiple rows as well as too many null fields. Any help would be greatly appreciated.
Edit:
By multiple rows I mean duplicate rows. Also, I am aware that a left join produces null values on the right side of the join. What I meant to say is that I'm getting more null values than I should be as the data is within the database.
To clarify, I'm trying to create a list of recent reviews with the most recent listed first. Each review consists of a username, 11 categories (each one is an integer value), overall rating (int value), notes (string), image (URL), and whiskey name (string).
1) You can't be getting multiple SAME rows, since you use DISTINCT. (by multiple do you mean duplicate?)
2) You get null fields because you are using LEFT JOIN and your tables cannot be joined (some "ON clause" cannot be evaluated as true)
It turns out that there was nothing wrong with my query. The person whose database I'm using isn't maintaining it so there are several reviews for the same product and user where only the overall rating is different. Also, there are many reviews on products that don't even exist. I should've looked at the database closer to begin with as deleting all of the erroneous rows solved my problem. Thanks for all the input.

What type of mysql query do you run to compare two fields in separate tables?

I have a mysql table(table1) which has the following row:
topic_id: 1
topics: programming
description: A programming language is an artificial language designed to...
I have another table(table2) with this row:
desc_id: 1
description: In mathematics and computer science, an algorithm is an effective...
topics: mathematics, computer science, programming
What I'm looking to do is to run a query to compare the two topics fields and let me know which topics exist in table2 that don't exist in table1.
For instance, comparing the two above I'd like to run a query to let me know that topics mathematics and computer science don't exist in table1.
I would use a subquery, but it can also be done with innerjoins :
SELECT *
FROM `table2`
WHERE `topics` NOT IN (
SELECT DISTINCT(topics)
FROM `table1`
)
you can try NOT IN
i.e.
SELECT topics FROM table2 where topics NOT IN( select topics from table1)
If you normalized your table2 so that the topics list is in a separate sub-table, this would be a trivial query. As it stands now, it's difficult as by default mysql won't see those seperate topics in table2.topics as discrete topics. It's just a long string that happens to have commas in there.
Thankfully, MySQL has the find_in_set() function, which can help out immensely, but this function isn't available elsewhere. Not having access to your dataset, I'm just guessing here, but this should do the trick:
SELECT table1.topics, count(table1.topic_id) AS cnt
FROM table1
LEFT JOIN table2.topics ON FIND_IN_SET(table1.topics, table2.topics) = 0
GROUP BY table1.topics
HAVING cnt = 0
Basically, join the tables wherever the table1 topic is NOT in a table2 topic and count how many times the table1 topic shows up like this. If it shows up zero times, then it's present in at least one record in table2.
normalize by creating a third table, one that links table 2 to table 1 with a many to many relationship.
Table_1
id, etc
Table_2
id, etc
Table_3
id, table1_id, table2_id
you could then use simple joins to create a query that will pull the relavent data
SELECT * FROM Table_1 LEFT JOIN Table_3 ON Table_1.id = Table_3.table1_id WHERE Table_3.table2_id = $table2_id
This will pull all topics for the course.

Categories