mysql order by clause outside select statement - mysql

I ran the following query by accident and it works, and now im' confused as to why it works. Can someone please explain how to interpret this query...
(select name from employe_info limit 100) order by name;
I always assumed the 'order by' has to be associate with an explicit select clause, but in this case it's outside the () and it works. This is probably not a good form, but i just want to know if this works by accident or is this expected?
Thanks!

You just apply sorting to subquery
See more in manual: https://dev.mysql.com/doc/refman/5.5/en/select.html
If ORDER BY occurs within a subquery and also is applied in the outer
query, the outermost ORDER BY takes precedence. For example, results
for the following statement are sorted in descending order, not
ascending order:
(SELECT ... ORDER BY a) ORDER BY a DESC;

Looks like that is only a partial query.
From UNION Syntax:
To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT
and a paragraph later:
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one.

Related

Ordered pagination with MySQL

UPDATE:
In the following question, I thought when you select rows, MySQL create a kind of row index, and then the LIMIT and OFFSET clause cuts off this list by its numbers. The problem is I'm using wrong values or field combination to sort the rows as the have almost the same value.
Here is my mistake, assuming to much "intelligence" form MySQL ;-)
The solution is always to have a more reliable sorting field as a fallback, like the ID, like so ORDER BY priority DESC, id ASC
This is a strict MySQL question. Why does it seem the LIMIT OFFSET clause is applied before the ORDER BY? or what am I missing?
Here is the example, first we select a list of rows ordered by a field called priority:
SELECT d0_.name, d0_.id AS id_0, d0_.priority AS priority_1 FROM destination d0_ WHERE d0_.active = 1 ORDER BY d0_.priority DESC;
The results looks like this:
Then I want to select the first 10 rows from this list using the following query:
SELECT d0_.name, d0_.id AS id_0, d0_.priority AS priority_1 FROM destination d0_ WHERE d0_.active = 1 ORDER BY d0_.priority DESC LIMIT 10 OFFSET 10;
And I've got this result:
Why does not the list goes from "Grandvalira" to "Sierra nevada"?
The problem of this, is not the actual order but some rows are never reached! like "Vallnord Ordino-ArcalĂ­s". As I change the OFFSET value, it does not go through all the rows, and it event repeats some rows.
This is the basic question. But this is giving me problems at the end when using the "KnpPaginatorBundle (2.5.3)" of Symfony. I thought was a problem of the php code, but mysql queries are giving this unexpected results for me.
Any help or clue of whats going on?
Thanks!
You are not getting the results you are expecting because your data has many rows with the same value for priority.
When you use 'order by' on priority, all the rows with priority can come in any order. There is no guarantee about the ordering with the same value of priority. To resolve the tie, you can add additional fields to your order by clause. Depending on your choice you might choose to include name or id field in the 'order by' clause.

MySQL GROUP BY order when no ORDER BY

In MySQL, what order is the resultset if GROUP BY is used but ORDER BY is not specified?
I have inherited code with queries like:
SELECT col1, COUNT(col1)
FROM table
GROUP BY col1
(Actually the SELECT statement can be much more complex than that, involving JOINs etc., but let's start with the base principle.) Note that there is no ORDER BY.
In, say, SQL Server BOL, I am told:
The GROUP BY clause does not order the result set. Use the ORDER BY
clause to order the result set.
I have been unable to find a statement as to whether MySQL GROUP BY does or does not promise a particular ordering from GROUP BY alone? If a MySQL reference could be provided to back up any answer that would be most welcome.
From the manual:
If you use GROUP BY, output rows are sorted according to the GROUP BY
columns as if you had an ORDER BY for the same columns. To avoid the
overhead of sorting that GROUP BY produces, add ORDER BY NULL:
SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
Relying on implicit GROUP BY sorting (that is, sorting in the absence
of ASC or DESC designators) is deprecated. To produce a given sort
order, use explicit ASC or DESC designators for GROUP BY columns or
provide an ORDER BY clause.

Exact same MYSQL query but different results on different servers

I have this query.
SELECT * FROM (SELECT * FROM private_messages ORDER BY id DESC) a
The "DESC" works on my local server but doesn't work on another server.
However if i just write it like this:
SELECT * FROM private_messages ORDER BY id DESC
it works on both servers. What would cause this?
This is going to be too long for a comment..
It's not a bug. It's documented here:
As of MySQL 5.7.6, the optimizer handles propagation of an ORDER BY
clause in a derived table or view reference to the outer query block
by propagating the ORDER BY clause if the following conditions apply:
The outer query is not grouped or aggregated; does not specify
DISTINCT, HAVING, or ORDER BY; and has this derived table or view
reference as the only source in the FROM clause. Otherwise, the
optimizer ignores the ORDER BY clause. Before MySQL 5.7.6, the
optimizer always propagated ORDER BY, even if it was irrelevant or
resulted in an invalid query.
However it's not the case for your query. So i guess your second server is running MariaDB which seams to ingnore any ORDER BY in a subquery without LIMIT
A "table" (and subquery in the FROM clause too) is - according to the
SQL standard - an unordered set of rows. Rows in a table (or in a
subquery in the FROM clause) do not come in any specific order. That's
why the optimizer can ignore the ORDER BY clause that you have
specified. In fact, SQL standard does not even allow the ORDER BY
clause to appear in this subquery (we allow it, because ORDER BY ...
LIMIT ... changes the result, the set of rows, not only their order).
You need to treat the subquery in the FROM clause, as a set of rows in
some unspecified and undefined order, and put the ORDER BY on the
top-level SELECT.
Why is ORDER BY in a FROM Subquery Ignored?
So best you can do is just to move the ORDER BY clause to the outer query. Or don't use a subquery at all.

How order by clause works in mysql, ordering shows wierd behaviour

I have a simple query
SELECT * FROM table_name order by non_unique_column LIMIT 0,50
This gives me list of records in some order.
But when I am removing * and putting some column names from the table, then it is changing the list order.
For some combination of columns in select clause it is giving different order.
I am not able to find, what pattern of column names in select clause gives different ordering.
So I am asking does any one had this kind of problem? or can any one suggest how the order by clause works in this scenario?
Note: If I am adding all the columns in select clause it gives me same result as *.
Please feel free to suggest any possible suggestion.
Thanks.
Update: Also when I am changing limit clause like LIMIT 0,50 to LIMIT 0,15, I am getting different sets of records.
Update2:
I have created a sqlfiddle :
http://sqlfiddle.com/#!2/8f2340/3
Please see the result from below queries
SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB`,`CON_FAX` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60
SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60
The only difference in the query is CON_FAX is not present in select clause of second query.
Please help me out why this difference is coming.
And also please see the result of below queries with different limit clause.
Note: It is second query from above queries.
SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60
SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,15
Thanks.
PERSONAL OPINION: I see this as a bug/defect, because even if I haven't defined any unique order by clause and mysql is applying some random ordering based on its calculations, I feel it should not depend on what is present in select clause. My problem is for a given set of records it should return same ordered records regardless of whatever column I am selecting.
The issue with this is because there is a duplicated value that you specify for your order by aka its either Mr. or Mrs. there is no guaranteed select order with this because they are all Mr. or Mrs.
if you want to ensure that it is always going to be in a specific order then you should also include the primary key as a second ordering to keep it all the same.. aka
ORDER BY CON_PREFIX ASC, M_ID ASC
as it stands right now ORDER BY CON_PREFIX is giving you exactly what it should be giving you, the prefixes in ascending order, there is nothing related to the limit for causing this, you simply just havent told MySQL how else you want the data to be returned to you.
to respond to your PERSONAL OPINION edit in the question....
what you are describing is unreasonable, think of it this way any default order that would be used to pull out data is now gone because you are specifying an order by. if there wasn't any order by on the clause then mysql has a generic select pattern but again that is gone once you put an order by on the query
The order by clause works from left to right
Let me give an example
If you use
SELECT serialNo,Name FROM table_name order by serialNo,Name;
what this does it it will order serialNo in the first instance and then it will order Name in the second instance . When it orders name in the second instance the oredering of the serialNo will change according to the ordering of the name .
Hope I was clear in my explanation .

Why ORDER BY + MAX() return the maximum value when I grouping?

I have this part of a query :
GROUP BY trackid
ORDER BY MAX(history.date) DESC
And I see that, when I grouping, it returns the row with maximum date for each group. Why this behaviour? Order should works on the whole rows...not on the grouping ?!?!?
EDIT (Example)
This is my whole query :
SELECT tracklist.value, history.date
FROM history JOIN tracklist ON history.trackid=tracklist.trackid
ORDER BY history.date DESC
The result is :
tracklist3 2011-04-27 15:40:36
tracklist2 2011-04-27 13:15:43
tracklist2 2011-04-02 00:30:02
tracklist2 2011-04-01 14:20:12
tracklist1 2011-03-02 14:13:58
tracklist1 2011-03-01 12:11:50
As you can see, all line is correctly ordered by history.date.
Now I'd like to group them, keeping for each group the row with MAX history.date.
So the output should be :
tracklist3 2011-04-27 15:40:36
tracklist2 2011-04-27 13:15:43
tracklist1 2011-03-02 14:13:58
I see that :
GROUP BY trackid
ORDER BY MAX(history.date) DESC
works correctly, but I really don't understand why it works :) Order by is for the whole rows, not for the grouping....
When you say SELECT trackid, MAX(history.date) ... GROUP BY trackid ORDER BY MAX(history.date) DESC you are really saying: "Show me for each tracklist the most recent history entry and please show me the tracklist first whose most recent history entry is (overall) most recent."
The ORDER BY is applied after the grouping, (that's why it comes after the GROUP BY in the SQL).
Note that in your example, you have SELECT tracklist.value, history.date instead of SELECT tracklist.value, MAX(history.date). That is just wrong and unfortunately MySQL does not give a warning but it choses a random history.date at its discretion.
ORDER BY MAX(history.date) DESC is somewhat redundant if all you want to do is order the result set. Ordering applies to the result set.
Consider the results if you remove the ORDER BY clause. Without that, your query would only be grouping on the trackid column, so it wouldn't be valid--you would need to add an aggregate function to the date column or add the date column to the GROUP BY clause. By adding the aggregate function to the ORDER BY clause, you are essentially telling the SQL engine that for each group of trackid, get the maximum date. This seems to be what you want.
It seems you do not fully understand the GROUP BY statement. I would recommend looking up a tutorial on it.
But essentially, the GROUP BY statement combines a number of rows into one. The column names you GROUP BY determine how unique the new combined rows will be. SQL doesn't know how to handle all of the non-grouped columns since each new combined row will be pulling data from a number of rows that contain different values in these columns. That's why you use aggregate functions on the non-grouped columns in the SELECT statement. The aggregate function MAX() looks at all of the values in the history.date column for the rows that are being combined and returns only one of them. Additionally, the ORDER BY clause can only use columns that are being selected, that's why ORDER BY also must contain aggregate functions.