Why is sql MAX function not working properly? - php

I have this query working to some extent.
It returns the correct value for 'rating' (which output as 7, the highest rating), but the output for 'content' is from a different row in the table. (not the row of the highest rating, which is 7)
$bestAnswerQuery = MYSQL_QUERY("SELECT content, MAX(rating) as rating FROM answers WHERE questionID = '$questionID'");
$fetchBestAnswer = MYSQL_FETCH_ASSOC($bestAnswerQuery);
echo "$fetchBestAnswer[content] $fetchBestAnswer[rating]";
Can anyone tell me why? I've searched and cannot find out why this isn't working properly.

This is not how aggregates like MAX work in SQL. Your confusion is coming from MySQL's (default) non-ANSI handling of aggregates.
Aggregates like MAX operate over groups. In the absence of a group by clause, the entire result set is considered to be a single group. Only expressions that are part of a group by clause can be included in a select clause without being enclosed in an aggregate. In the case where there is no group by, then all columns or expressions in the select clause must be contained in an aggregate.
However, MySQL's default configuration breaks this by allowing you to include non-grouped expressions in the select clause, but the row that any given expression uses to obtain its value is undefined; it could be any row within the group.
After that long-winded answer, if what you want to get is the maximum rating and the associated content column from the table for a given question, you can just do this:
select
rating,
content
from answers
where questionID = '$questionID'
order by rating desc
limit 1;

Change the query a little like this:
$bestAnswerQuery = mysql_query("SELECT content, rating as rating
FROM answers
WHERE questionID = '$questionID'
AND rating = MAX(rating)");

Related

How to target specific rows returned by mysqli query

Let's say I have a table with following columns: id-1, id-2, col-1, col-2, col-3
Here, id-1 is the primary key and is auto-incremented. id-2 is a different id and is not necessary to be unique. There are multiple instances of same id in that column. col-1, col-2, col-3 are just necessary columns.
I pass a query to select data from the table.
mysqli_query($connect, SELECT * FROM table WHERE id-2='some_specific_id')
It will return multiple rows. I would like to know how can I target specific rows, say row number 3.
First, use ":
mysqli_query($connect, "SELECT * FROM table WHERE id-2 = 'some_specific_id'");
Target specific row? Do you mean to limit the fetched rows? Or get the 3rd row?
For limiting the fetched rows, you can use LIMIT:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 3
For getting the third row:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 2, 1
Well although it seems you just rather needed to learn basic SQL to get your answer, there is still the question in the title, that may attract other people whose problem is formulated exactly like that. So goes the answer:
Mysqli is not very convenient for this task, so we would use PDO.
In case your query is intended to return multiple rows and you need to address one of them by number (which is rather makes little sense, but anyway), use fetchAll() method:
$stmt = $connect->prepare("SELECT * FROM table WHERE id2=?");
$stmt->execute(['some specific id']);
$data = $stmt->fetchAll();
and you will be able to address returned rows by number, starting from zero:
echo $data[0]['col1'];
However, it makes more sense to address the returned rows by some unique id. In this case just add this unique field fiset in the field list and then use the special PDO street magic:
$stmt = $connect->prepare("SELECT id1, table.* FROM table WHERE id2=?);
$stmt->execute(['some specific id']);
$data = $stmt->fetchAll(PDO::FETCH_UNIQUE);
and you will be able to address returned rows by that unique field :
echo $data[$id1]['col1'];
Use LIMIT to get what you want like:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 2, 1;
Or, if you want to fetch from array, then use the 3rd index of array.
LIMIT Explanation:
The following illustrates the LIMIT clause syntax with two arguments:
SELECT
column1,column2,...
FROM
table
LIMIT offset , count;
Let's examine the LIMIT clause parameters:
The offset specifies the offset of the first row to return. The offset of the first row is 0, not 1.
The count specifies the maximum number of rows to return.

Get previous 10 row from specific WHERE condition

Im currently working on a project that requires MySql database and im having a hard time constructing the query that i want get.
i want to get the previous 10 rows from the specific WHERE condition on my mysql query.
for example
My where is date='December';
i want the last 10 months to as a result.
Feb,march,april,may,june,july,aug,sept,oct,nov like that.
Another example is.
if i have a 17 strings stored in my database. and in my where clause i specify that WHERE strings='eyt' limit 3
Test
one
twi
thre
for
payb
six
seven
eyt
nayn
ten
eleven
twelve
tertin
fortin
fiftin
sixtin
the result must be
payb
six
seven
Thanks in advance for your suggestions or answers
If you are using PDO this is the right syntax:
$objStmt = $objDatabase->prepare('SELECT * FROM calendar ORDER BY id DESC LIMIT 10');
You can change ASC to DESC in order to get either the first or the last 10.
Here's a solution:
select t.*
from mytable t
inner join (select id from mytable where strings = 'eyt' order by id limit 1) x
on t.id < x.id
order by t.id desc
limit 3
Demo: http://sqlfiddle.com/#!9/7ffc4/2
It outputs the rows in descending order, but you can either live with that, or else put that query in a subquery and reverse the order.
Re your comment:
x in the above query is called a "correlation name" so we can refer to columns of the subquery as if they were columns of a table. It's required when you use a subquery as a table.
I chose the letter x arbitrarily. You can use anything you like as a correlation name, following the same rules you would use for any identifier.
You can also optionally define a correlation name for any simple table in the query (like mytable t above), so you can refer to columns of that table using a convenient abbreviated name. For example in t.id < x.id
Some people use the term "table alias" but the technical term is "correlation name".

ROWNUM doesn't work; trying to grab info on specific row range in SQL query

I have a bit of code that counts the number of rows upon an SQL query and then does another query to grab information on the last four rows. I've used ROWNUM, but it doesn't work.
$newscount = $db->query("
SELECT *
FROM news
");
$counter = $newscount->rowCount();
$grabnewsmsg = $db->query("
SELECT *
FROM news
WHERE ROWNUM >= $counter-4 -- this particular part doesn't owrk
ORDER BY updateno DESC -- an A_I column
");
I've commented the specific areas I'm having problems. The A_I part is fine, since there should be a unique identifier for each row, but ROWNUM just doesn't work despite what I have read on other sites in addition to other questions/answers on SO. It returns an error column rownum does not exist.
I want to get information on solely the last four rows ($query->rowCount()-4), but I can't select via a certain updateno threshhold. If a user deletes a row, the A_I column cannot be appropriately used to determine the row number.
Additionally, I've tried the below:
$grabnewsmsg = $db->query("
SELECT *
FROM news
ORDER BY updateno DESC
LIMIT 0,4
");
And while this gives the desired results, I'm still not sure why ROWNUM doesn't work.
You need to understand the meaning of that AUTO_INC thingy. It is called an unique identifier, and for a reason. "Unique" means no other row should have the same identifier ever.
Yet it has absolutely nothing to do with whatever enumeration. So -
I have an autoincrementing column titled 'updateno' which corresponds to the number of the row.
this is what you are doing wrong.
As a matter of fact, you don't need such a field at all. If you wnat to enumerate your fields - do in on the fly. If you want an identifier - use a conventional name for this - "id"
While for the whatever "rownum" feature you need another mysql operator, namely LIMIT

I need to select newest rows from a MySQL database, but verify that I am also returning a row with a given ID

I'm new to this, sorry if the title is confusing. I am building a simple php/mysql gallery of sorts. It will show the newest 25 entries when a user first goes to it, and also allows off-site linking to individual items in the list. If the URL contains an ID, javascript will scroll to it. But if there are 25+ entries, it's possible that my query will fetch the newest results, but omit an older entry that happens to be in the URL as an ID.
That means I need to do something like this...
SELECT * FROM `submissions` WHERE uid='$sid'
But after that has successfully found the submission with the special ID, also do
SELECT * FROM `submissions` ORDER BY `id` DESC LIMIT 0, 25`
So that I can populate the rest of the gallery.
I could query that database twice, but I am assuming there's some nifty way to avoid that. MySQL is also ordering everything (based on newest, views, and other vars) and using two queries would break that.
You could limit across a UNION like this:
(SELECT * FROM submissions WHERE uid = '$uid')
UNION
(SELECT * FROM submissions WHERE uid <> '$uid' ORDER BY `id` LIMIT 25)
LIMIT 25
Note LIMIT is listed twice as in the case that the first query returns a result, we would have 26 results in the union set. This will also place the "searched for" item first in the returned sort result set (with the other 24 results displayed in sort order). If this is not desirable, you could place an ORDER BY across the union, but your searched for result would be truncated if it happened to be the 26th record.
If you need 25 rows with all of them being sorted, my guess is that you would need to do the two query approach (limiting second query to either 24 or 25 records depending on whether the first query matched), and then simply insert the uid-matched result into the sorted records in the appropriate place before display.
I think the better solution is:
SELECT *
FROM `submissions`
order by (case when usid = $sid then 0 else 1 end),
id desc
limit 25
I don't think the union is guaranteed to return results in the order of the union (there is no guarantee in the standard or in other databases).

PHP SQL COUNT AND GET DATA

I would like get the id and the number of id. So, I write this command sql:
SELECT count(id), id
FROM tblExample
It's doesn't work. Have you a solution for me ? For to get the value of my id and the number of id.
Or a function PHP for count my resultset.
Just add a GROUP BY id:
SELECT id, COUNT(id)
FROM tblExample
GROUP BY id;
Demo
Update:
The query you posted:
SELECT count(id), id
FROM tblExample;
Won't work in most of the RDBMS and it shouldn't. In SQL Server, you will got an error; saying that:
Column 'id' is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
Strangely though, MySQL allow this(The OP didn't say what RDBMS he is using), and in this case, it will get an arbitrary value (this is also depends on an option to set), for the id column, and the COUNT in this case would be all the id's count.
But it is not recommended to do so.

Categories