Rewrite the SQL in version 5.7 - mysql

I have a following SQL which works in mysql version 5.6 but is breaking in mysql version 5.7.x.
SELECT * FROM (SELECT * FROM photos WHERE photoable_type = 'Mobilehome'
AND photoable_id IN (SELECT id FROM mobilehomes WHERE
mobilehomes.community_id = 1) AND photos.image_file_size IS NOT NULL
AND photos.is_published IS TRUE ORDER BY photos.priority ASC) AS tmp_table
GROUP BY photoable_id
It's throwing me following error:
Expression #1 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'tmp_table.id' which is not functionally
dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by

In this case or you change the sql mode for instrcut the db to work as mysql 5.6 version or you can adeguate your query to the new behavior
In this second case
If you use group by whithout aggregation function this mean that for all the column different from photoable_id you accept casual result
This mean that you could, probably, also accepted an aggregated result based greagtion function eg: on min() or max ()
assuming your tables containg col1, col2, .. the you must declare explicitally the column you need
SELECT photos.photoable_id, min(col1), min(col2),....
FROM photos
INNER JOIN mobilehomes ON mobilehomes.community_id = 1
AND photos.photoable_type = 'Mobilehome'
AND photos.photoable_id = mobilehomes.id
AND photos.image_file_size IS NOT NULL
AND photos.is_published IS TRUE
GROUP BY photos.photoable_id
ORDER BY photos.priority ASC
Looking to your code seems also that you could avoid the subquery

Related

Getting latest quote data for stock

I am collecting quote data and chose opt_ticker and quoteTimeStamp as the primary key so that I can store unique quotes over time. I now want to create a view where I can see the latest quote for each opt_ticker (data base has other opt_tickers with unique quotes as well). Basically want to see the latest quote for each stock/option.
In the example above, I want to get that last row as it is the latest timestamp for that particular contract.
I thought this query would do the trick but mysql complains that I need to do a group by.
select symbol,opt_ticker,ask,bid,exp,strike,type,max(quoteTimeStamp)
from optionquotes
group by opt_ticker
21:36:42 select symbol,opt_ticker,ask,bid,exp,strike,type,max(quoteTimeStamp) from optionquotes group by opt_ticker,symbol LIMIT 0, 1000 Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'od2.optionquotes.ask' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by 0.000 sec
Here my server info if it helps
Server
Product: (Ubuntu)
Version: 5.7.30-0ubuntu0.16.04.1
Connector
Version: C++ 8.0.20
This sounds so easy but I am having the toughest time figuring this out, thank you in advance.
In MySQL 5.x you can do:
select *
from optionquotes
where (opt_ticker, quoteTimeStamp) in (
select opt_ticker, max(quoteTimeStamp)
from optionquotes
group by opt_ticker
)
In MySQL 8.x you can do:
select *
from (
select *,
row_number() over(partition by opt_ticker order by quoteTimeStamp desc) as rn
from optionquotes
) x
where rn = 1
Just to round out the answers, here is a canonical way to do this using a join:
SELECT oq1.*
FROM optionquotes
INNER JOIN
(
SELECT opt_ticker, MAX(quoteTimeStamp) AS maxQuoteTimeStamp
FROM optionquotes
GROUP BY opt_ticker
) oq2
ON oq1.opt_ticker = oq2.opt_ticker AND
oq1.quoteTimeStamp = oq2.maxQuoteTimeStamp;

have any SQL GROUP_CONCAT alternative function?

here i was past my sql query.
any body know GROUP_CONCAT alternative function so let me know ?
SQL Error :
<h1>A Database Error Occurred</h1>
<p>Error Number: 1140</p>
<p>In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'smartsaver.ud.id'; this is incompatible with sql_mode=only_full_group_by</p>
SQL Command :
SELECT ud.id, ud.url, d.document_name, d.d
GROUP_CONCAT(LEFT(REPLACE(url, "document", "thumb"), CHAR_LENGTH(REPLACE(url, "document", "thumb")) - LOCATE(".", REVERSE(REPLACE(url, "document", "thumb")))), ".", "png")
ud.document_url
END as new_url, CASE WHEN ud.type = 1 THEN "Image" WHEN ud.type = 2 THEN "Video" WHEN ud.type = 3 THEN "File" WHEN ud.type = 4 THEN "Text" ELSE "" END as type, d.added_on, ud.type as document_type
FROM tbl_uplaod_document ud
JOIN tbl_document d ON d.id = ud.document_id
LEFT OUTER JOIN tbl_document_project_relation pr
ON pr.document_id = ud.document_id
WHERE ud.is_active = 1
AND d.is_active = 1
AND ud.user_id = 1
AND ud.document_id = 116
LIMIT 10
#dev5 Your code to hard to read
Expression #1 of SELECT list is not in GROUP BY clause and contains non aggregated column 'smartsaver.ud.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by.
will be simply solved by changing the sql mode in MySQL by this command:
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
Thank You :-)
You have a select with an aggregation function. That makes the query an aggregation function. But there is no group by. Happily, MySQL now generally returns an error in this case.
Earlier versions of MySQL allowed a malformed query such as your using the default settings. It would return values for the unaggregated columns from arbitrary rows. The default settings have changed to generate an error.
You should add a group by for all non-aggregated columns in the select:
group by ud.id, ud.url, d.document_name, d.d, . . .
Your code is rather hard to read, so it is hard to pick out the unaggregated columns.

mysql error "ERROR 3029 (HY000): Expression #1 of ORDER BY contains aggregate function and applies to the result of a non-aggregated query"

I am executing the below query
SELECT DISTINCT n.nid AS entity_id
FROM node n
INNER JOIN og_membership om ON n.nid=om.etid AND om.entity_type='node'
INNER JOIN foster_animal_capacity fc ON n.nid=fc.person_id
LEFT OUTER JOIN field_data_field_attributes fa ON n.nid=fa.entity_id
LEFT OUTER JOIN foster_person_black_outs fb ON n.nid=fb.person_id
WHERE -- n.nid = 1441663 AND
(om.gid = 464) AND (fc.animal_type_id = 3)
AND ((fc.capacity - fc.occupied)>=1)
AND ((fb.start_date IS NULL) OR (fb.end_date < 1523577600) OR (fb.start_date > 1522540800))
AND ((SELECT pid FROM `animal_history` WHERE `TYPE` = 'Foster Return'
AND pid = n.nid ORDER BY DATE_FORMAT(FROM_UNIXTIME( UNIX_TIMESTAMP( ) - MAX( CAST(`time` AS UNSIGNED) ) ) ,'%e')));
The query executing perfectly in MySql 5.5.5
But showing the below error in MySql 5.7.21
ERROR 3029 (HY000): Expression #1 of ORDER BY contains aggregate function and applies to the result of a non-aggregated query
Why is this happening? And how can I overcome this issue?
I am not able to find any documentation for the error code 3029
As mentioned in MySQL documention :
MySQL 5.7.5 and up implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them. (Before 5.7.5, MySQL does not detect functional dependency and ONLY_FULL_GROUP_BY is not enabled by default. For a description of pre-5.7.5 behavior, see the MySQL 5.6
For detail please check:
MySQL Handling of GROUP BY

MySQL query with distinct and order by showing error 3065(HY000)

I am using linux mint in my machine and trying to execute a query. After the execution, an error is displayed
ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list, references column 'shelterl_local.animal.changed' which is not in SELECT list; this is incompatible with DISTINCT
I added line
[mysqld]
sql-mode=''
in /etc/mysql/my.cnf file and restarted mysql. But still getting the same error. I referred many solutions but nothing worked for me. My query is
SELECT DISTINCT fs.etid AS etid FROM og_membership fs
LEFT OUTER JOIN node animal ON animal.nid = fs.etid LEFT OUTER JOIN
field_data_field_for_animal dfa ON dfa.field_for_animal_value = fs.etid
LEFT OUTER JOIN node pastid ON pastid.nid = dfa.entity_id WHERE ( (fs.gid =
464) OR
(animal.nid IN
(1196113,1211208,1218831,1243640,1254254,
1253603,1249890,1261729,1261282,1258378,1273745,1270760,
1279219,1276040,1276031,1275684,1288727,1289306,1300545,
1313770,1313761,1313755,1313746,1313330,1312388,1310673,
1309431,1315024,1333640,1328041,1323565,1327216,1330104,
1327786,1326810,1335812,1333094,1341309,1340358,1348088,
1351077,1351071,318214,1342698,1472755,1491527,1351652,1353488,
1507763,1342713)) )AND (fs.entity_type = 'node')
AND (animal.type = 'animal') AND (animal.status = 1) AND (pastid.title LIKE
'%A%')
ORDER BY animal.changed DESC LIMIT 0,300;
Is it possible to remove this error permanently and execute the query? Please help
Your initial query is equivalent to the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY field2 DESC LIMIT 0,300
This can't make logical sense, because each value of field1 in the result set may have multiple values of field2 associated with it. The error you are seeing is MySQL's way of saying it can't figure out what you want to do. One workaround would be to sort on an aggregate of field2, e.g. try the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY MAX(field2) DESC -- or AVG(field2), or MIN(field2), etc.
LIMIT 0,300
You need to actually select field2
SELECT DISTINCT field1 AS f1,
field2
FROM table t
--Joins and conditions
ORDER BY field2 DESC LIMIT 0,300
UPDATE:
I know sometimes theres errors when using DISTINCT and ORDER BY in the same query. To fix this i would give the animal.changed section an ALIAS such as [animal.changed] and then if you ORDER BY [animal.changed] this should not error. At least i know this definitely works in SQL server
E.G
SELECT DISTINCT animal.changed AS [animal.changed]
FROM .....
ORDER BY [animal.changed]
This is very basic but would allow you to use DISTINCT and ORDER BY in the same query which is the current error you're getting.
If you select a column then sorting can only be done for this column. If you need to sort by another column, then necessarily include this column in the selection.
//wrong.....
$sql="Select DISTINCT Rubrika from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
//RIGHT!!!
$sql="Select DISTINCT Rubrika, View from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
I also encountered the same issue and abled to resolve it. Since I'm using Windows I'll post fix for windows but similar fix will work for linux as well.
This is happening because ONLY_FULL_GROUP_BY mode is enabled by mysql. You can disable this by modifying my.ini file. (In linux this would be my.cnf).
Open my.ini file.
This file might be located in a hidden directory ProgramData.
C:\ProgramData\MySQL\MySQL Server 8.0
Find following config which is placed under [mysqld] section.
sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Remove ONLY_FULL_GROUP_BY from here
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Restart mysql server
net stop MYSQL80
net start MYSQL80

Prestashop - List view filter

I insert an other column in the list view of my module inserting the values with getList function, I modified the sql to filter in the renderList function but I can't use the alias in where clause.
How can I fix it?
The error i got is the next:
Uncaught Unknown column 'product_supplier_name' in 'where clause'<br /><br />
SELECT SQL_CALC_FOUND_ROWS a.* , s.name AS product_supplier_name FROM ps_supplier_bill a LEFT JOIN ps_supplier s ON s.id_supplier = a.id_product_supplier WHERE 1 AND product_supplier_name LIKE '%fa%' ORDER BY product_supplier_name asc LIMIT 0,50
The proper query should be this:
SELECT SQL_CALC_FOUND_ROWS a.* , s.`name` AS product_supplier_name FROM `ps_supplier_bill` a LEFT JOIN `ps_supplier` s ON s.`id_supplier` = a.`id_product_supplier` WHERE 1 AND s.`name` LIKE '%fa%' ORDER BY s.`name` asc LIMIT 0,50
It's not possible use directly an alias in WHERE, because chronologically, WHERE happens before SELECT, which always is the last step in the execution chain. REFER
From MySQL doc:
Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.
MySQL doc