mysql: get top answer - mysql

I have a table called answers with 2 rows:
questionid - answer
as you can probably guess questionid stores the question id number and answer stores the answer, the answers are just numbers 1 to 8
I want to display the top answer.
eg:
questionid - answer
4 - 7
4 - 3
4 - 3
2 - 3
6 - 7
7 - 1
9 - 8
1 - 5
top answer = 3
i've tried:
SELECT answer FROM answers WHERE questionid='$qid' ORDER BY answer DESC LIMIT 1
and
SELECT DISTINCT answer FROM answers WHERE questionid='$qid' ORDER BY answer DESC LIMIT 1
$qid = page id ie: /question.php?qid=4
but both return incorrect.
Update:
Is there away of showing the result without using:
while($row = mysql_fetch_array($result)) {
// stuff here
}
as I just want to show 1 result (ie the top answer) based on $qid

There are multiple ways to do this (HAVING(), WHERE, MAX(), etc) The commonality is GROUP BY.
SELECT answer, COUNT(answer) FROM questions GROUP BY answer ORDER BY COUNT(answer) DESC LIMIT 1
This will return:
3 - 3
Read more about GROUP BY.
UPDATE
Seems you modified your question after I posted this answer.
If you want to limit the query to a specific question, add a WHERE clause as the other questions.
... FROM questions WHERE questionid = X GROUP BY ...
Note: Be mindful of SQL Injection.
When you only have 1 record, you can forego the while loop and just access the top result.
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
Note: You'll like want to do more error checking (e.g. ensure a result was returned). Also, don't use mysql_* functions as they are now deprecated. Use MySQLi or PDO instead.

SELECT count(*) AS answer_count, answer FROM answers WHERE questionid='$qid' GROUP BY answer ORDER BY answer_count DESC LIMIT 1

Related

MYSQL Query to extract to value only [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed last month.
I want to write a mysql query that selects the final result in the figure below :
Thanks
Any solution, for this question.
This may help you, Execute query as below:
SELECT *
FROM tickets
GROUP BY device_id
HAVING key_field = MAX(key_field)
ORDER BY device_id ASC
Will produce result as you expected:
Key
ID device
ticket Number
212
1
594
211
2
147

MySQL Stuck with Group BY and ONLY_FULL_GROUP_BY error [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 4 years ago.
first I would like to say that I'm aware of the only_full_group_by restriction and I understand why it's behaving this way.
And I would prefer have a fine query that desactivating this option.
SELECT campaigns.uuid, campaigns.name, coupons.name, coupons.value, coupons.product_id, coupons.uuid FROM `campaigns`
LEFT JOIN coupons ON coupons.uuid = campaigns.coupon_id
GROUP BY coupons.product_id
ORDER BY coupons.value DESC
In my coupons table I can have several coupons related to the same product_id, but I would like to return only one coupon by product, the one with the higher value.
I'm scratching my head from 4 hours but I can't find out to do it.
Thank you for your help.
Here is the structure of coupons table (useless fields removed) :
uuid
name
value
product_id
Where I can have 3 differents row :
uuid1 - name1 - 1.5 - 1
uuid2 - name2 - 0.80 - 2
uuid3 - name3 - 0.90 - 1
What I would like to return is just :
uuid1 - name1 - 1.5 - 1
uuid2 - name2 - 0.80 - 2
And skip the name 3 since it's the same product ID and I only want to return the coupon with the highest value.
In fact I also have other table joins to retrieve some data but I skipped them from the example to make it clearer.
Hope it explains better what I mean.
the simplest way is add agregation function for the columns not involved in group by
SELECT
min(campaigns.uuid)
, min(campaigns.name)
, min(coupons.name)
, min(coupons.value)
, coupons.product_id
, min(coupons.uuid )
FROM `campaigns`
LEFT JOIN coupons ON coupons.uuid = campaigns.coupon_id
GROUP BY coupons.product_id
ORDER BY coupons.value DESC
in the versions that precede mysql 5.7 the result for aggreated columns not involved in group was unpredictable (as in you code) .. in version starting from 5.7 you can substitute the unpredictable result with a controlled b y aggregation function result

select a random rows from table

I have two tables one called topic as shown below!
topic_id topic_name
1 topic 1
2 topic 2
3 topic 3
and another table called questions as shown
q_id question_name topic_id
1 question 1 1
2 question 2 1
3 question 3 1
4 question 4 2
5 question 5 2
6 question 6 2
7 question 7 3
8 question 8 3
9 question 9 3
i want to choose random 2 question from given three topic. Someone please help me to fix this issue
Get list of topics with their question IDs GROUP_CONCAT([column] order by RAND()).
And then link table to itself.
SELECT t.q_id, t.question_name, t.topic_id
FROM table t
JOIN (
SELECT topic_id, SUBSTRING_INDEX(GROUP_CONCAT(q_id ORDER BY RAND()), ',', 2) as qList
FROM table GROUP BY topic_id
) tGrouped ON FIND_IN_SET(t.q_id, tGrouped.qList)>0
One can sort the rows randomly and then fetch the top row from this random order
For two random questions which could have same topic:
SELECT * FROM questions
ORDER BY RAND()
LIMIT 2
For two random questions which should have different topic:
Use 2 different queries which take as parameters two different topic_ids (t1, t2):
First select 2 random topic ids (similarly to above code):
SELECT topic_id FROM topics
ORDER BY RAND()
LIMIT 2
Then select 2 random questions with these topics ids (2 select statements)
SELECT * FROM questions
WHERE topic_id = t1
ORDER BY RAND()
LIMIT 1
SELECT * FROM questions
WHERE topic_id = t2
ORDER BY RAND()
LIMIT 1
UPDATE (after OP's comment and explanation)
To obtain two random questions from every topic use a variation of the above solutions:
3 select statements (one for each topic):
SELECT * FROM questions
WHERE topic_id = needed_topic_id_here
ORDER BY RAND()
LIMIT 2
repeat the select for every topic_id.
Presumably these select statements could be combined into one big select statement, but i'm not sure at this point.
Note as pointed out in another answer, this could be less efficient (to randomly select in pure sql) and a better solution would be to pre-compute random indices in PHP (or whatever your platform is) and then actually select the random questions. Since no language is mentioned in the question, i'll leave it here (and point to the other answer(s) for this approach)
You can use ORDER BY RAND() and LIMIT 2 in the query but it runs painfully slow for tables that have thousand of records or more.
A better approach for big tables is to get the bounding values of the PK field using the WHERE condition you need, generate 2 random numbers smaller between these bounding values in PHP then issue 2 MySQL queries to get 2 questions.
Something along these lines:
$query = '
SELECT MIN(q_id) AS min_id, MAX(q_id) AS max_id
FROM questions
WHERE topic_id = 1 # put the filtering you need here
';
// Run the query
// ... use your regular PHP code for database access here ...
// get and store the returned values in PHP variables $minId and $maxId
// Keep the generated random values here to avoid duplicates
$list = array();
// Get N random questions from the database
for ($cnt = 0; $cnt < N; $cnt ++) {
// Generate a new ID that is not in the list
do {
$id = rand($minId, $maxId);
} while (in_array($id, $list);
// Put it into the list to avoid generating it again
$list[] = $id;
// Get the random question
$query = "
SELECT *
FROM questions
WHERE topic_id = 1
AND q_id <= $id
ORDER BY q_id DESC
LIMIT 1
";
// Run the query, get the question
// ... use your regular PHP code for database access here ...
}
No matter what queries you run (these or others provided by other answer), you need indexes on q_id and the columns used in the WHERE clause.
I hope q_id is the PK of the table which means it already is an UNIQUE INDEX.
Provide 3 topic ids to get 2 questions at random:
select
q.question_name
from
topics t,
questions q
where
t.topic_id = q.topic_id and
t.topic_id in (1, 2, 3) /*define your 3 given topics*/
order by rand() limit 0,2;

Sum Of mysql table record

I have a table named tbl_Question and a column named INT_MARK which has different marks for different questions. Like this:
VH_QUESTION INT_MARK
----------- --------
Q1 2
Q2 4
My question is: How to get a random set of 20 questions whose total sum of marks is 50?
select VH_QUESTION, sum(INT_MARK) from tbl_Question
group by VH_QUESTION
having sum(INT_MARK) > 50
order by rand() limit 1
I think this question may help you - seems a very similar problem.
If that don't work, I'd try to divide the problem in two: first, you make a combinatory of your questions. Then, you filter them by it's sum of points.
I couldn't find, however, how to produce all combinations of the table. I don't know how difficult that would be.
select VH_QUESTION, sum(INT_MARK) from tbl_Question
group by VH_QUESTION
having sum(INT_MARK) >= 50
order by rand() limit 20
Quick answer
SELECT * ,SUM(INT_MARK) as total_mark FROM tbl_Question
GROUP BY VH_QUESTION
HAVING total_mark="50"
ORDER BY RAND()
LIMIT 5
it returns 0 line when no answers are possible but each time it finds one the questionsare random.
You could check the benchmark to see if you can have a faster query for large tables.

Returning query results in predefined order

Is it possible to do a SELECT statement with a predetermined order, ie. selecting IDs 7,2,5,9 and 8 and returning them in that order, based on nothing more than the ID field?
Both these statements return them in the same order:
SELECT id FROM table WHERE id in (7,2,5,9,8)
SELECT id FROM table WHERE id in (8,2,5,9,7)
I didn't think this was possible, but found a blog entry here that seems to do the type of thing you're after:
SELECT id FROM table WHERE id in (7,2,5,9,8)
ORDER BY FIND_IN_SET(id,"7,2,5,9,8");
will give different results to
SELECT id FROM table WHERE id in (7,2,5,9,8)
ORDER BY FIND_IN_SET(id,"8,2,5,9,7");
FIND_IN_SET returns the position of id in the second argument given to it, so for the first case above, id of 7 is at position 1 in the set, 2 at 2 and so on - mysql internally works out something like
id | FIND_IN_SET
---|-----------
7 | 1
2 | 2
5 | 3
then orders by the results of FIND_IN_SET.
Your best bet is:
ORDER BY FIELD(ID,7,2,4,5,8)
...but it's still ugly.
Could you include a case expression that maps your IDs 7,2,5,... to the ordinals 1,2,3,... and then order by that expression?
All ordering is done by the ORDER BY keywords, you can only however sort ascending and descending. If you are using a language such as PHP you can then sort them accordingly using some code but I do not believe it is possible with MySQL alone.
This works in Oracle. Can you do something similar in MySql?
SELECT ID_FIELD
FROM SOME_TABLE
WHERE ID_FIELD IN(11,10,14,12,13)
ORDER BY
CASE WHEN ID_FIELD = 11 THEN 0
WHEN ID_FIELD = 10 THEN 1
WHEN ID_FIELD = 14 THEN 2
WHEN ID_FIELD = 12 THEN 3
WHEN ID_FIELD = 13 THEN 4
END
You may need to create a temp table with an autonumber field and insert into it in the desired order. Then sort on the new autonumber field.
Erm, not really. Closest you can get is probably:
SELECT * FROM table WHERE id IN (3, 2, 1, 4) ORDER BY id=4, id=1, id=2, id=3
But you probably don't want that :)
It's hard to give you any more specific advice without more information about what's in the tables.
It's hacky (and probably slow), but you can get the effect with UNION ALL:
SELECT id FROM table WHERE id = 7
UNION ALL SELECT id FROM table WHERE id = 2
UNION ALL SELECT id FROM table WHERE id = 5
UNION ALL SELECT id FROM table WHERE id = 9
UNION ALL SELECT id FROM table WHERE id = 8;
Edit: Other people mentioned the find_in_set function which is documented here.
You get answers fast around here, don't you…
The reason I'm asking this is that it's the only way I can think of to avoid sorting a complex multidimensional array. I'm not saying it would be difficult to sort, but if there were a simpler way to do it with straight sql, then why not.
One Oracle solution is:
SELECT id FROM table WHERE id in (7,2,5,9,8)
ORDER BY DECODE(id,7,1,2,2,5,3,9,4,8,5,6);
This assigns an order number to each ID. Works OK for a small set of values.
Best I can think of is adding a second Column orderColumn:
7 1
2 2
5 3
9 4
8 5
And then just do a ORDER BY orderColumn