MySql using correct syntax for the over clause - mysql

What is the correct syntax to get the over clause to work in mysql?
I would like to see the total sms's sent by each user without grouping it with the group by clause.
SELECT
username,
count(sentSmsId) OVER (userId)
FROM
sentSmsTable,
userTable
WHERE
userId = sentUserId;

MySQL 8 has got the window functions! Therefore, you can write your query in it like this:
SELECT username,
count(sentSmsId) OVER (partition by userId)
FROM sentSmsTable
JOIN userTable ON userId = sentUserId;

There is no OVER clause in MySQL that I know of, but here is a link that might assist you to accomplish the same results:
http://explainextended.com/2009/03/10/analytic-functions-first_value-last_value-lead-lag/
Hope this helps.

MySQL does not currently support window functions, so over() will only yield syntax errors (or garbage, if it's accepted regardless).

MySQL Doesn't have window functions until the most recent release: MySQL 8 (release in April, 2018). MS SQL Server also accepts OVER clause.
The syntax is:
function(col1) OVER (PARTITION BY col2 ORDER BY col3)
Check out https://mysqlserverteam.com/mysql-8-0-2-introducing-window-functions/ for more examples.

Related

"group by desc" syntax error on mysql 8.0 which is fine on 5.7

The statement is like SELECT * FROM db.table group by id desc;
Would raise an error like
15:02:24 SELECT * FROM db.table group by id
desc LIMIT 0, 10 Error Code: 1064. You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'desc LIMIT 0, 10' at line 1 0.00014
sec
on MySQL 8.0.13 in Ubuntu 18.04 Desktop 64bit
which would be fine on MySQL 5.7 in Windows or CentOS or Ubuntu.
I know basically, the select statement is like.
SELECT statement... [WHERE condition | GROUP BY `field_name(s)` HAVING condition] ORDER BY `field_name(s)` [ASC | DESC];
So is this 5.7's problem not to issue the error?
Or something more complicated on SQL standard?
I have the same issue, so for MySQL 8, I used the sql like that:
SELECT * FROM db.table
group by id
order by id desc
Taking from #P.Salmon's comment for the question.
If you look up the select statement in the manual
http://dev.mysql.com/doc/refman/5.7/en/select.html you will see
that up to 5.7 asc|desc are optional modifiers to the group by
statement which are no longer present from 8.0.and if you look at the
upgrade documentation
https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-sql-changes
This deprecation is documented.
Since this situation, #Linda Li's answer could be a good option.
This query makes no sense:
SELECT *
FROM db.table
GROUP BY id DESC;
You are doing an aggregation query. So (presumably), the table has multiple rows per id. Those are condensed down to one row. What values should be used for the other columns? It is sad that MySQL ever supported this syntax. So a welcome change is that ONLY_FULL_GROUP_BY is now the default.
A small hint is that using an aggregation query with no aggregation functions is suspicious.
Perhaps you want:
select id, min(col1), min(col2), . . .
from t
group by id;
Or more likely, you want a particular row, such as the "earliest" or "most recent", something like:
select t.*
from t
where t.createdAt = (select min(t2.createdAt) from t t2 where t2.id = t.id);

SQL Basics: Simple WITH [duplicate]

I'm trying to use MySQL to create a view with the "WITH" clause
WITH authorRating(aname, rating) AS
SELECT aname, AVG(quantity)
FROM book
GROUP BY aname
But it doesn't seem like MySQL supports this.
I thought this was pretty standard and I'm sure Oracle supports this. Is there anyway to force MySQL to use the "WITH" clause? I've tried it with the MyISAM and innoDB engine. Both of these don't work.
Update: MySQL 8.0 is finally getting the feature of common table expressions, including recursive CTEs.
Here's a blog announcing it: http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/
Below is my earlier answer, which I originally wrote in 2008.
MySQL 5.x does not support queries using the WITH syntax defined in SQL-99, also called Common Table Expressions.
This has been a feature request for MySQL since January 2006: http://bugs.mysql.com/bug.php?id=16244
Other RDBMS products that support common table expressions:
Oracle 9i release 2 and later:
http://www.oracle-base.com/articles/misc/with-clause.php
Microsoft SQL Server 2005 and later:
http://msdn.microsoft.com/en-us/library/ms190766(v=sql.90).aspx
IBM DB2 UDB 8 and later:
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0000879.htm
PostgreSQL 8.4 and later:
https://www.postgresql.org/docs/current/static/queries-with.html
Sybase 11 and later:
http://dcx.sybase.com/1100/en/dbusage_en11/commontblexpr-s-5414852.html
SQLite 3.8.3 and later:
http://sqlite.org/lang_with.html
HSQLDB:
http://hsqldb.org/doc/guide/dataaccess-chapt.html#dac_with_clause
Firebird 2.1 and later (the first Open Source DBMS to support recursive queries):
http://www.firebirdsql.org/file/documentation/release_notes/html/rlsnotes210.html#rnfb210-cte
H2 Database (but only recursive):
http://www.h2database.com/html/advanced.html#recursive_queries
Informix 14.10 and later:
https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.sqls.doc/ids_sqs_with.htm
You might be interested in something like this:
select * from (
select * from table
) as Subquery
You've got the syntax right:
WITH AuthorRating(AuthorName, AuthorRating) AS
SELECT aname AS AuthorName,
AVG(quantity) AS AuthorRating
FROM Book
GROUP By Book.aname
However, as others have mentioned, MySQL does not support this command. WITH was added in SQL:1999; the newest version of the SQL standard is SQL:2008. You can find some more information about databases that support SQL:1999's various features on Wikipedia.
MySQL has traditionally lagged a bit in support for the SQL standard, whereas commercial databases like Oracle, SQL Server (recently), and DB2 have followed them a bit more closely. PostgreSQL is typically pretty standards compliant as well.
You may want to look at MySQL's roadmap; I'm not completely sure when this feature might be supported, but it's great for creating readable roll-up queries.
Oracle does support WITH.
It would look like this.
WITH emps as (SELECT * FROM Employees)
SELECT * FROM emps WHERE ID < 20
UNION ALL
SELECT * FROM emps where Sex = 'F'
#ysth WITH is hard to google because it's a common word typically excluded from searches.
You'd want to look at the SELECT docs to see how subquery factoring works.
I know this doesn't answer the OP but I'm cleaning up any confusion ysth may have started.
Building on the answer from #Mosty Mostacho, here's how you might do something equivalent in MySQL,for a specific case of determining what entries don't exist in a table, and are not in any other database.
select col1 from (
select 'value1' as col1 union
select 'value2' as col1 union
select 'value3' as col1
) as subquery
left join mytable as mytable.mycol = col1
where mytable.mycol is null
order by col1
You may want to use a text editor with macro capabilities to convert a list of values to the quoted select union clause.
MariaDB is now supporting WITH. MySQL for now is not.
https://mariadb.com/kb/en/mariadb/with/
Have you ever tried Temporary Table?
This solved my convern:
create temporary table abc (
column1 varchar(255)
column2 decimal
);
insert into abc
select ...
or otherwise
insert into abc
values ('text', 5.5), ('text2', 0815.8);
Then you can use this table in every select in this session:
select * from abc inner join users on ...;
WITH authorRating as (select aname, rating from book)
SELECT aname, AVG(quantity)
FROM authorRating
GROUP BY aname

Window function in MySQL queries

Is there a way to use window functions in MySQL queries dynamically within a SELECT query itself? (I know for a fact that it is possible in PostgreSQL).
For example, here is the equivalent query in PostgreSQL:
SELECT c_server_ip, c_client_ip, sum(a_num_bytes_sent) OVER
(PARTITION BY c_server_ip) FROM network_table;
However, what would be the corresponding query in MySQL?
Starting MySQL 8.0, you can now use OVER and partition, so consider upgrading to the latest version :)
Hope this might work:
select A.c_server_ip, A.c_client_ip, B.mySum
from network_table A, (
select c_server_ip, sum(a_num_bytes_sent) as mySum
from network_table group by c_server_ip
) as B
where A.c_server_ip=B.c_server_ip;

Can not Access Aliased Columns in Select Statement (MySQL)

I have a problem with Aliased Columns in MySQL!
My Query:
SELECT Price AS Pr, (Pr*10/100) FROM MyTable;
MySQL WorkBench Error: UnKnown Column 'Pr' in Field List !!!
I tested my query in W3Schools with no error !
I tested my query in W3Schools with no error!
This doesn't prove that your query is valid.
You can only use aliases in GROUP BY, ORDER BY or HAVING clauses. Your usage variant is not allowed, because the value of alias is not known when MySQL is selecting the 2-nd column.
I've got a suspicion that W3Schools uses MS Access to run user queries, and MS Access does allow such atrocity as referencing column aliases in a SELECT clause that are defined in the same SELECT clause.
The standard doesn't allow this and MySQL does follow standard in this particular case.
As for solution to your problem, I can see two options.
The more generic solution, which would run in probably any SQL product, would be to use a derived table:
SELECT
Pr,
(Pr * 10 / 100) AS SomethingElse
FROM
(
SELECT
SomeComplexExpression AS Pr
FROM MyTable
) AS sub
;
The other option would be to use a variable, which is MySQL-specific:
SELECT
#Pr := SomeComplexExpression AS Pr,
(#Pr * 10 / 100) AS SomethingElse
FROM MyTable
;
Finally, if you need to test/demonstrate if something can/cannot work in MySQL, I'd recommend using SQL Fiddle.

MySQL "WITH" clause

I'm trying to use MySQL to create a view with the "WITH" clause
WITH authorRating(aname, rating) AS
SELECT aname, AVG(quantity)
FROM book
GROUP BY aname
But it doesn't seem like MySQL supports this.
I thought this was pretty standard and I'm sure Oracle supports this. Is there anyway to force MySQL to use the "WITH" clause? I've tried it with the MyISAM and innoDB engine. Both of these don't work.
Update: MySQL 8.0 is finally getting the feature of common table expressions, including recursive CTEs.
Here's a blog announcing it: http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/
Below is my earlier answer, which I originally wrote in 2008.
MySQL 5.x does not support queries using the WITH syntax defined in SQL-99, also called Common Table Expressions.
This has been a feature request for MySQL since January 2006: http://bugs.mysql.com/bug.php?id=16244
Other RDBMS products that support common table expressions:
Oracle 9i release 2 and later:
http://www.oracle-base.com/articles/misc/with-clause.php
Microsoft SQL Server 2005 and later:
http://msdn.microsoft.com/en-us/library/ms190766(v=sql.90).aspx
IBM DB2 UDB 8 and later:
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0000879.htm
PostgreSQL 8.4 and later:
https://www.postgresql.org/docs/current/static/queries-with.html
Sybase 11 and later:
http://dcx.sybase.com/1100/en/dbusage_en11/commontblexpr-s-5414852.html
SQLite 3.8.3 and later:
http://sqlite.org/lang_with.html
HSQLDB:
http://hsqldb.org/doc/guide/dataaccess-chapt.html#dac_with_clause
Firebird 2.1 and later (the first Open Source DBMS to support recursive queries):
http://www.firebirdsql.org/file/documentation/release_notes/html/rlsnotes210.html#rnfb210-cte
H2 Database (but only recursive):
http://www.h2database.com/html/advanced.html#recursive_queries
Informix 14.10 and later:
https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.sqls.doc/ids_sqs_with.htm
You might be interested in something like this:
select * from (
select * from table
) as Subquery
You've got the syntax right:
WITH AuthorRating(AuthorName, AuthorRating) AS
SELECT aname AS AuthorName,
AVG(quantity) AS AuthorRating
FROM Book
GROUP By Book.aname
However, as others have mentioned, MySQL does not support this command. WITH was added in SQL:1999; the newest version of the SQL standard is SQL:2008. You can find some more information about databases that support SQL:1999's various features on Wikipedia.
MySQL has traditionally lagged a bit in support for the SQL standard, whereas commercial databases like Oracle, SQL Server (recently), and DB2 have followed them a bit more closely. PostgreSQL is typically pretty standards compliant as well.
You may want to look at MySQL's roadmap; I'm not completely sure when this feature might be supported, but it's great for creating readable roll-up queries.
Oracle does support WITH.
It would look like this.
WITH emps as (SELECT * FROM Employees)
SELECT * FROM emps WHERE ID < 20
UNION ALL
SELECT * FROM emps where Sex = 'F'
#ysth WITH is hard to google because it's a common word typically excluded from searches.
You'd want to look at the SELECT docs to see how subquery factoring works.
I know this doesn't answer the OP but I'm cleaning up any confusion ysth may have started.
Building on the answer from #Mosty Mostacho, here's how you might do something equivalent in MySQL,for a specific case of determining what entries don't exist in a table, and are not in any other database.
select col1 from (
select 'value1' as col1 union
select 'value2' as col1 union
select 'value3' as col1
) as subquery
left join mytable as mytable.mycol = col1
where mytable.mycol is null
order by col1
You may want to use a text editor with macro capabilities to convert a list of values to the quoted select union clause.
MariaDB is now supporting WITH. MySQL for now is not.
https://mariadb.com/kb/en/mariadb/with/
Have you ever tried Temporary Table?
This solved my convern:
create temporary table abc (
column1 varchar(255)
column2 decimal
);
insert into abc
select ...
or otherwise
insert into abc
values ('text', 5.5), ('text2', 0815.8);
Then you can use this table in every select in this session:
select * from abc inner join users on ...;
WITH authorRating as (select aname, rating from book)
SELECT aname, AVG(quantity)
FROM authorRating
GROUP BY aname