MySQL GROUP BY on multiple columns, codeigniter - mysql

I know the title sounds like the a common question, but I have looked around here and can't seem to find problems (with answers) the same as mine.
So this is my case: I have three tables (major_criteria, questions, and results) ... There are multiple major criteria, and one major criteria has multiple questions. The table results holds all the users' answers to those questions.. Using this code:
$this->db->simple_query('set session group_concat_max_len=1000000');
$this->db->select('*, GROUP_CONCAT(CONCAT("<tr><td>", eq_question, "</td><td id=fix>", r_value) SEPARATOR "</td></tr>") as quesrate', false);
$this->db->from('evaluation_result');
$this->db->join('evaluation_question', 'evaluation_question.eq_ai=evaluation_result.er_eq_ai', left);
$this->db->join('evaluation_major_criteria', 'evaluation_major_criteria.emc_ai=evaluation_question.eq_emc_ai', left);
$this->db->join('rating', 'rating.r_ai=evaluation_result.er_rate', left);
$this->db->where('er_il_ai', $inst);
$this->db->where('er_ay_ai', $aca);
$this->db->where('er_sem_ai', $sem);
$this->db->where('er_et_ai', $evaltype);
$this->db->order_by('emc_code', 'asc');
$this->db->group_by('emc_code', 'asc');
$query=$this->db->get();
Assuming I have three users who answered, I was able to achieve this:
A. Major Criteria 1
Question 1 | Answer 1
Question 1 | Answer 2
Question 1 | Answer 3
Question 2 | Answer 1
Question 2 | Answer 2
Question 2 | Answer 3
B. Major Criteria 2
Question 1 | Answer 1
Question 1 | Answer 2
Question 1 | Answer 3
Question 2 | Answer 1
Question 2 | Answer 2
Question 2 | Answer 3
...
I was successfully able to group them by major criteria. But It's close to what I want to achieve. What I want is to group it by question too, so it doesn't repeat by how many the users have answered.
Something like this:
A. Major Criteria 1
Question 1 | Answer 1, Answer 2, Answer 3
Question 2 | Answer 1, Answer 2, Answer 3
B. Major Criteria 2
Question 1 | Answer 1, Answer 2, Answer 3
Question 2 | Answer 1, Answer 2, Answer 3
...
I have tried using two group_by and it doesn't work like how I want it to, according to this: Using group by on multiple columns
I have tried putting DISTINCT in GROUP_CONCAT but it gives me really weird combination of questions (some still repeated) under correctly grouped major criteria.
I have tried nested select statements with one or two group_by.
Idk. Maybe I'm looking at the wrong direction?
I have ran out of resources. I've looked around and tried everything I found, still no luck. This is my last resort. I'm using codeigniter for this, btw.
EDIT:
I also have this code from when I first made the page:
$this->db->select('*', false);
$this->db->from('evaluation_result');
$this->db->join('evaluation_question', 'evaluation_question.eq_ai=evaluation_result.er_eq_ai', left);
$this->db->join('evaluation_major_criteria', 'evaluation_major_criteria.emc_ai=evaluation_question.eq_emc_ai', left);
$this->db->join('rating', 'rating.r_ai=evaluation_result.er_rate', left);
$this->db->where('er_il_ai', $inst);
$this->db->where('er_ay_ai', $aca);
$this->db->where('er_sem_ai', $sem);
$this->db->where('er_et_ai', $evaltype);
$this->db->where('eq_s_ai', 2);
$this->db->order_by('emc_code', 'asc');
$this->db->group_by('eq_ai');
$query=$this->db->get();
And it groups by question. Now I have two queries, one that groups by major criteria, and one that groups by question. I guess I just have to combine them? But idk how.

Related

Select users who answered all the questions

I have tables like these:
Table ANSWER
idAnswer idQuestion Status idGame
----------------------------------------
1 9 1 1
2 6 NULL 1
3 6 1 2
4 3 NULL 2
5 1 1 3
6 6 1 3
7 9 1 4
8 6 1 4
Table GAME:
idGame idUser
----------------
1 Greg
2 Greg
3 Jack
4 Frank
I want to get only those who answered the same question as the game n°4, like this:
Desired result:
idUser
-------
Greg
Frank
Status is used to check if the question has been answered. If it is NULL, the user didn't answer it.
Here, Frank had a very similar game (it's obvious, because it's the same, the n°4).
Greg didn't played a similar game, but answered in 2 others the same questions, so he appears in the result.
Jack did answered one of the question (n°6) but didn't answered the other one (n°9), so Jack doesn't appear.
So, the result includes only those who answered the same questions as another game, no matter if it's in a similar game or in multiple one.
Games are randomly generated. Sometimes, user can answer a question they already encounter or/and answered. (Like Greg, in game 1 and 2).
I tried a lot of queries. I can post them if you want.
Thanks for the answers!
You can try this:
SELECT g.idUser, COUNT(*) as NumberOfAnswers
FROM answer a
INNER JOIN game g ON a.idGame = g.idGame
WHERE a.idQuestion IN (9,6)
GROUP BY g.idUser
HAVING NumberOfAnswers = 2
I think this solution match your requirements if the users cannot answer the same question twice in the same game and if you doesn't mind to show users who has answered more questions.
EDIT:
For a more generic solution, you could adapt the query to something like this:
SELECT g.idUser, COUNT(*) as NumberOfAnswers
FROM answer a
INNER JOIN game g ON a.idGame = g.idGame
WHERE a.idCuestion IN (SELECT idQuestion FROM answer WHERE idGame=[DESIRED_GAME])
GROUP BY g.IdUser
HAVING NumberOfAnswers = (SELECT COUNT(*) FROM answer WHERE idGame = [DESIRED_GAME]

Query to retrieve main records in one table and its all sub records from another table

Let us suppose we have tables like questions and answers
Questions table
qno question
1 first question
2 second question
Answers table
ano qno answer
1 1 first answer for q1
2 1 second answer for q1
3 2 first answer for q2
4 1 third answer for q1
5 2 second answer for q2
Now I need a single query in mysql that can output each question and all of its answers
Expected output
qno ano question answer
--- --- ---------- -------------------
1 0 first question
1 1 first answer for q1
1 2 second answer for q1
1 4 third answer for q1
2 0 second question
2 3 first answer for q2
2 5 second answer for q2
Normally a JOIN doesn't output results in the format you show as your desired result. The JOIN operator in SQL matches rows from one table to rows from the other, so it will produce the question repeatedly, which is not what you want.
To get what you want, use UNION instead of JOIN, and position them into columns like you want:
(SELECT qno, 0, question, NULL AS `answer` FROM questions)
UNION
(SELECT qno, ano, NULL, answer FROM answers)
ORDER BY qno, ano
For what it's worth, I agree with the comments from Strawberry. I wouldn't actually do this in my application. I would fetch the data in a simpler format, and in my application code present the data in the layout desired.
My example above is only to show that manipulating the data into that layout in SQL makes the code less clear.

Using two columns to obtain count on another in SQL

I have a simple question that I wasn't really sure how to search for (or title!). I apologize if this has been asked a million times. For the following table, how do I generate a report that will detail the number of companies that a person has worked for and how many people have also worked for that same number? So, for example, this table should return:
people, companiesperperson
1, 1
2, 2
1, 3
for the following table called personalinfo:
id_number first last company
1 John Doe Intel
2 John Doe Microsoft
3 Phil Jenkins Amgen
4 Phil Jenkins Bayer
5 Phil Jenkins Sanofi
6 Josh Edwards Walgreens
7 Amy Dill URS
8 Amy Dill ARCADIS
Let me know if this is still confusing and if I can further clarify what I am looking to do.
Thanks!
This is a rough estimate of the query but
SELECT count as companiesperperson, COUNT(first, last) as people FROM
(SELECT COUNT(company) as count, first, last FROM personalinfo GROUP BY (first, last)) as a
GROUP BY count
To explain the query first in the subquery we are asking for the names and count of companies after splitting up all the rows by names
Then in the outer query we split up all the rows by their count and ask how many unique names can be found in each group.
There may be a few syntax errors I've left straggling but the group by feature is really what's essential to understanding how to solve this question.

finding most 'popular' items in multiple tables in mySQL [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have multiple tables of items which are 'ordered' by their ratings/popularity.
I need to combine all the tables into one table with a top 10.
The top 10 will combine the number of times an entry (with wildcard as the names may be slightly different) appears in all the lists and it's position in the tables.
is this possible?
I've researched Joins but it seems quite a complicated procedure given there are two factors (nubmer of entries and position in the tables).
Apologies for being vague, I didn't think I was doing so. This is my first question on stackoverflow
table 1 table 2 table 3
--------------------
bob | bob | Ian
fred | james |john
kate | fred | bob
mary | brian | brian
the 'rankings' results of the three tables need to appear in a final table (called 'final' for example)
As you can see Bob would rank highly on 'final'.
But Ian appears only once, even though he is top of the list in table 3.
Fred appears in position 2 and position 3 so should he be higher or lower than Ian.
would I need an algorithm for the sorting or is there some trick in mySQl that will examine the rankings?
You can return them with a ranking, but you need to define how that rank applies.
For example if you just return the ranking from each table then Bob appears twice in the first position. If you add those 2 ranks together it gives 2. How do you compare that to Ian who is only ranked 1 once.
For this you are probably best building a ranking from the last row (or calculating it as total number of rows - ranking).
You can get a basic ranking from each table with the following:-
SELECT some_name, #rank_1:=#rank_1 + 1 AS ranking
FROM table_1
CROSS JOIN (SELECT #rank_1:=0) sub_1
UNION ALL
SELECT some_name, #rank_2:=#rank_2 + 1 AS ranking
FROM table_2
CROSS JOIN (SELECT #rank_2:=0) sub_2
UNION ALL
SELECT some_name, #rank_2:=#rank_2 + 1 AS ranking
FROM table_2
CROSS JOIN (SELECT #rank_2:=0) sub_3
but this will give you each record from each table and their ranking.
As it is though, you have nothing to say that Bob is the first record on table_1. While it may be the first record, as far as the order returned this is not a certainty.

MySQL select distinct dateTime. Cant figure this query out

My users answer two different questions, they are added to my answers_table as one row each. I'm trying to count how many users have answered my questions which seems simple at first. Count(*) and divide by 2. YES! But: the users can add new questions as they go, so suddenly there might be three questions, all answers/3 becomes an incorrect number of users if there was two questions for a while and then three, for example!
Can anyone figure out a query for doing this? So far I've got
SELECT COUNT(DISTINCT date) as totNum FROM login_answers
But it doesn't take the time in consideration. Meaning i just get the amount of answers in total for that day, not knowing how many questions was available that day.
Here's my table:
qid is the QuestionID so i guess thats somewhere to start?
id qid answer date deviceID
1502 2 2 2012-10-19 08:42:41 7
1503 1 3 2012-10-19 08:51:53 7
1504 2 2 2012-10-19 08:51:53 7
1505 1 4 2012-10-19 09:05:23 7
1506 2 2 2012-10-19 09:05:23 7
1507 1 4 2012-10-19 09:40:59 7
My proposed solution would be to store a session Id or some auto-generated key against the answers to uniquely identify a "session" of 2, 3 or more answers from a single person.
The query would simply be
SELECT COUNT(DISTINCT session_id) totNum
FROM login_answers
With your current schema with no identifiable key, it's quite hard to answer your question correctly if at all possible.