After Updating to MySQL 5.7.11 we are getting a number of errors related to the sql_mode including only_full_group_by.
Research shows we can turn this off but it would probably be better to know how to achieve the intended goal with properly structured SQL statements.
Error:
#1140 - In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'tblslideshow.slideImage'; this is incompatible with sql_mode=only_full_group_by
Query:
SELECT
tblslideshow.slideImage,
COUNT(tblslideshow.slideID) AS countVal
FROM
tblslideshow
WHERE
tblslideshow.parentID = 3424
The goal is to return a list of values but also a Count for all returned records.
What's the best way to achieve this goal without having to change the MySQL my.ini ? And why is it a Group By error is we're not even grouping? Or is Grouping part of the proper solution?
Expected Result should be:
slideImage | countVal
Image1.jpg | 3
Image2.jpg | 3
Image3.jpg | 3
Edit: Since we are using PHP and MySQLi it may be wiser to exclude the Count() and just use "mysqli_num_rows"
When you use Aggregate function, you need to add non-aggregate columns on Group by clause.
SELECT
tblslideshow.slideImage,
COUNT(tblslideshow.slideID) AS countVal
FROM
tblslideshow
WHERE
tblslideshow.parentID = 3424
Group by tblslideshow.slideImage
EDIT
You can try to use subquery on select
SELECT t.slideImage,
(
SELECT
COUNT(tblslideshow.slideID) AS countVal
FROM
tblslideshow
WHERE
tblslideshow.parentID = 3424
) countVal
FROM tblslideshow t
WHERE t.parentID = 3424
What you are looking for is COUNT OVER, available as of MySQL 8.0:
SELECT
tblslideshow.slideImage,
COUNT(*) OVER () AS countVal
FROM
tblslideshow
WHERE
tblslideshow.parentID = 3424;
This keeps the single rows and adds the aggregate value to them.
Related
mysql rename column output query
Hey guys!
I'm trying to create a kind of alias to use as a variable in grafana but I'm not getting the desired result...
My intention is that the query returns only the alias created from the query and not the name of the column itself.
See my query below:
select dcontext as Recebidas from cdr_local where dcontext = 'inc_alvoko' group by dcontext;
With this query I get the answer as shown below:
+------------+
| Recebidas |
+------------+
| inc_alvoko |
+------------+
Where is the column name "inc_alvoko" I want to rename it to "Received" but I can't...
I will greatly appreciate any member who can help me with this detail!
seems you are looking for a "translation" for your countents so you could try using case
select distinct
case when dcontext = 'inc_alvoko' then 'Received' END Recebidas
from cdr_local w
where dcontext = 'inc_alvoko'
and if you need distinct result but not use a ggregation function you should not use group by but use DISTINCT clause in select .
the improper use of group bt without aggregation function produce error (by default) in mysql version starting by 5.7
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'shows.b.show_title' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
SELECT b.show_title as show_title FROM `shows` `b`
WHERE `b`.`active` = 1
GROUP BY SUBSTRING(show_title, 1, 1)
I'm naming all columns in select query so why the error?
I know the workaround of disabling ONLY_FULL_GROUP_BY from sql_mode but how do i solve the error with the query?
Q: why the error?
Consider two rows with show_title values of 'True Detective' and 'True Lies'
The expression in the GROUP BY is going to return T for both of those rows, so those rows are going to be collapsed into a single row in the resultset.
The query can return only a single value for a column in the collapsed row, and it's indeterminate/ambiguous which of the two values to return. With ONLY_FULL_GROUP_BY in sql_mode, MySQL is adhering more closely to the ANSI SQL specification; the 1055 error is behavior similar to what we observe in other relational DBMS e.g. Oracle, Microsoft SQL Server, Teradata, DB2, et al.
Q: how do i solve the error with the query?
The normative pattern is to use an aggregate function to specify which value (out of a set of possible values) to return.
For example, MAX() or MIN(). Demonstration:
SELECT SUBSTR(b.show_title,1,1) AS s1
, MAX(b.show_title) AS max_show_title
, MIN(b.show_title) AS min_show_title
FROM shows b
WHERE b.active = 1
GROUP BY SUBSTR(b.show_title,1,1)
will avoid the 1055 error, and could return e.g.
s1 max_show_title min_show_title
-- --------------- ---------------
T True Lies True Detective
Simply use these two queries and run them as query.
Your problem will be fixed asap.
No need to restart mysql
solution :
run this query :
SET sql_mode = '';
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
I have a table in a database mysql (5.7.21) like this:
+----------+--------------+-----------+-----------+
| id_price | id_reference | price_usd | unix_time |
+----------+--------------+-----------+-----------+
And I need to extract the average price (price_usd) grouped by week of year, or month (unix_time).
I prepare this query:
SELECT CONCAT(WEEKOFYEAR(FROM_UNIXTIME(unix_time)),
'-',
YEAR(FROM_UNIXTIME(unix_time))) as date,
AVG(price_usd) AS "model"
FROM price_avg
INNER JOIN reference ON reference.id_reference=price_avg.id_reference
WHERE price_avg.id_reference=1
GROUP BY WEEKOFYEAR(FROM_UNIXTIME(unix_time)),
YEAR(FROM_UNIXTIME(unix_time)),
price_avg.id_reference
ORDER BY unix_time ASC
The inner join is useful to get the name of the product having the the id.
I get this error:
#1055 - Expression #1 of SELECT list is not in GROUP BY clause and
contains nonaggregated column 'name_of_db.price_avg.unix_time' which is not
functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
I cannot change the settings of MySQL (I can't disable ONLY_FULL_GROUP_BY mode or anything else).
How do I have to change the query to extract the data in MySQL 5.7.21?
Thanks in advance.
You can use sub query so that it will be a full group by.
Select `date`,
AVG(price_usd) AS "model"
From (
SELECT CONCAT(WEEKOFYEAR(FROM_UNIXTIME(unix_time)),
'-',
YEAR(FROM_UNIXTIME(unix_time))) as `date`,
price_usd
FROM price_avg
INNER JOIN reference ON reference.id_reference=price_avg.id_reference
WHERE price_avg.id_reference=1
) t
GROUP BY `date`
ORDER BY substring(`date`, -4), substring(`date`, 1, 2) ASC;
Result:
date model
48-1998 11.99
36-2001 19.99
I solved with this query:
SELECT DATE_FORMAT(FROM_UNIXTIME(unix_time),'%Y-%m') as date, AVG(price_usd) AS model FROM price_avg INNER JOIN reference ON reference.id_reference=price_avg.id_reference WHERE price_avg.id_reference=1
GROUP BY date, price_avg.id_reference ORDER BY date ASC
I have week and year inverted but I can resolve in client enviroment!
Thank you all.
Hit this same problem, reported it as a possible bug on MySQL:
https://bugs.mysql.com/bug.php?id=90792&thanks=4
From the initial response, it sounded like it might be treated as a bug and fixed, but I think the follow-up suggests that GROUP BY expressions (instead of columns) aren't part of the SQL standard, and that determining if a complex expression is completely derived from GROUPed expressions is difficult and is, for now at least, something they decided not to pursue:
https://mysqlserverteam.com/when-only_full_group_by-wont-see-the-query-is-deterministic/
There are some workarounds in the meantime.
This question already has answers here:
Error related to only_full_group_by when executing a query in MySql
(18 answers)
Closed 5 years ago.
The following CodeIgniter query gives an error telling;
Expression #22 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'hw3.1.hw_homework.id' which is not functionally
dependent on columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by
SELECT *, `studentid`, COUNT(studentid),
`be_user_profiles`.`first_name`, `be_user_profiles`.`last_name`
FROM `be_user_profiles`
JOIN `be_users` ON `be_users`.`id`=`be_user_profiles`.`user_id`
JOIN `hw_homework` ON `be_user_profiles`.`user_id`=`hw_homework`.`studentid`
WHERE `be_user_profiles`.`advisor` = '20'
AND `hw_homework`.`date` < '2018-06-15 00:00:00'
AND `hw_homework`.`date` > '2017-08-24 00:00:00'
AND `active` = 1
GROUP BY `be_user_profiles`.`user_id`
ORDER BY COUNT(studentid) DESC
Filename: modules/organization/models/Mhomework.php
Line Number: 226
$this->db->select('*,studentid,COUNT(studentid),be_user_profiles.first_name,be_user_profiles.last_name');
$this->db->from('be_user_profiles');
$this->db->join('be_users','be_users.id=be_user_profiles.user_id');
$this->db->join('hw_homework','be_user_profiles.user_id=hw_homework.studentid');
$this->db->where('be_user_profiles.advisor',$id);
$this->db->where('hw_homework.date <',$to);
$this->db->where('hw_homework.date >',$from);
$this->db->where('active',1);
$this->db->group_by('be_user_profiles.user_id');
$this->db->order_by('COUNT(studentid)','DESC');
$query = $this->db->get();
I removed studentid or added group_by studentid etc but none of them worked.
I know that I can set global SQL mode but I think it is not a solution for me.
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
I want to fix the code not the way around.
In standard SQL it's very difficult to use SELECT * in a query with GROUP BY. Why? Standard SQL requires SELECTEed columns to also appear in the GROUP BY clause, with a few exceptions for columns with values that are functionally dependent on ones mentioned in the GROUP BY.
To write an aggregate query it's easiest to enumerate the columns you want in your SELECT and again in your GROUP BY. MySQL's notorious nonstandard extension to GROUP BY lets you ask for columns that aren't mentioned in the GROUP BY clause, and proceeds to return some unpredictable value for those columns.
To fix this "right" as opposed to hack around it, you need to get rid of the *. Change
$this->db->select('*,studentid,COUNT(studentid),be_user_profiles.first_name,be_user_profiles.last_name');
to
$this->db->select('studentid,COUNT(studentid),be_user_profiles.first_name,be_user_profiles.last_name');
and, for best results, change
$this->db->group_by('be_user_profiles.user_id');
to
$this->db->group_by('studentid,be_user_profiles.user_id');
I have a question similar to the one found here: How to find rows in SQL that start with the same string (similar rows)?, and this solution works in MySQL 5.6 but not 5.7.
I have a database (t) with multiple columns, the important ones being id and filepath, and what I am trying to accomplish is retrieving all the file paths which have the same last 5 characters. The following works in MySQL5.6, and the second SELECT works fine in 5.7:
SELECT id, filepath FROM t
WHERE SUBSTRING(filepath, -5) IN
(
SELECT SUBSTRING(filepath, -5)
FROM t
GROUP BY SUBSTRING(filepath, -5)
HAVING COUNT(*) > 1
)
But when I try to run it on 5.7 I get the error
Expression #1 of HAVING clause is not in GROUP BY clause and contains
nonaggregated column 't.filepath' which is not functionally dependent on
columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by
Sample data:
id filepath
1 /Desktop/file1.txt
2 /Desktop/file2.txt
3 /Desktop/file1.txt
and I would want to return the rows with id 1 and 3. How can I fix this for MySQL5.7?
EDIT: Also can anybody point me in the right direction for the SQL to remove the duplicates? So I would want to remove the entry for id 3 but keep the entry for id 1 and 2.
Please read the mysql documentation on the subject GROUP BY and sql_mode only_full_group_by (like your error message says):
https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
I think changing the inner query to this might fix the problem:
SELECT SUBSTRING(filepath, -5) AS fpath
FROM t
GROUP BY fpath
HAVING COUNT(fpath) > 1
Edit:
As to your question of why adding the "AS fpath" works:
Adding the alias "fpath" is just a clean way to do this. The point of ONLY_FULL_GROUP_BY is that each field you use in the SELECT, HAVING, or ORDER BY must also be in the GROUP BY.
So I added the fpath-alias for multiple reasons:
For performance: The query you wrote had SUBSTRING(filepath, -5) twice, which
is bad for performance. Mysql has to execute that SUBSTRING call twice,
while in my case it has to do it only once (per row).
To fix the group-by issue: You had COUNT() in the having, but "" was not in your GROUP BY statement (I'm not even sure whether that would be possible). You had to count "something", so since "fpath" was in your SELECT and in your GROUP BY, using that as your COUNT() would fix the problem.
I prefer not to put subqueries in an IN() predicate because MySQL tends to run the subquery many times.
You can write the query differently to put the subquery in the FROM clause as a derived table. That will make MySQL run the subquery just once.
SELECT id, filepath
FROM (
SELECT SUBSTRING(filepath, -5) AS suffix, COUNT(*) AS count
FROM t
GROUP BY suffix
HAVING count > 1
) AS t1
JOIN t AS t2 ON SUBSTRING(t2.filepath, -5) = t1.suffix
This is bound to do a table-scan though, so it's going to be a costly query. It can't use an index when doing a substring comparison like that.
To optimize this, you might create a virtual column with an index.
ALTER TABLE t
ADD COLUMN filepath_last VARCHAR(10) AS (SUBSTRING_INDEX(filepath, '/', -1)),
ADD KEY (filepath_last);
Then you can query it like this, and at least the subquery uses an index:
SELECT id, filepath
FROM (
SELECT filepath_last, COUNT(*) AS count
FROM t
GROUP BY filepath_last
HAVING count > 1
) AS t1
STRAIGHT_JOIN t AS t2 ON t2.filepath_last = t1.filepath_last
The solution that ended up working for me was found here: Disable ONLY_FULL_GROUP_BY
I ran SELECT ##sql_mode then SET ##sql_mode = followed by a string containing all the values returned by the first query except for only_full_group_by, but I'm still interested in how this is to be accomplished without changing the SQL settings.