MySQL GROUP BY and ORDER BY order - mysql

Does it matter which comes after which? I mean if I do
SELECT * FROM table GROUP BY x ORDER BY y
will the results first be grouped and then ordered?

ORDER is the last clause to be executed.
The order of execution
FROM clause
WHERE clause (the reason why you can't use alias on this clause)
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
For more info, please click here

First WHERE condition
Second GROUP BY
Third one is ORDER BY
Example :
SELECT * FROM table GROUP BY columnanme ORDER BY columnanmae

In MySQL, a GROUP BY clause has the side effect of sorting columns as well. If you already have a GROUP BY clause in your query that produces the desired sort order, there's no need for an ORDER BY.

Related

SQL OrderBy Clause Not Working with max alias

I have a query
Select tableA.*, max(`queue_position`) AS `product_advertisements.queue_position`
from tableA join tableB
group by tableA.attribute
order by `product_advertisements.queue_position` ASC
When the query runs, its not actually sorting by the queue position,
This is my return https://gyazo.com/471749b349d64e94707b9452d4b25417,
This is the expected output, https://gyazo.com/e8c92b2898a404781c9de095f1146143
Does it have something to do with ordering by the joined attribute? Why is my order by clause being ignored completely
I do not know the name of all columns, but I guess there is a column with the same name "product_advertisements.queue_position", and you do not want to order by it. Instead, you want to order by MAX(queue_position)
Try these 2 options:
Use the MAX column as the first column, and "ORDER BY 1", it would apply the order clause to the first column.
Select max(queue_position) AS product_advertisements.queue_position, tableA.*
from tableA join tableB
group by tableA.attribute
order by 1 ASC;
Use "max(queue_position)" in the ORDER CLAUSE
Select tableA.*, max(queue_position) AS product_advertisements.queue_position
from tableA join tableB
group by tableA.attribute
order by max(queue_position) ASC
Anyway, why do you select all columns (tableA.*), but group only by one? MySQL accepts it, but in other Databases it is not allowed.

MySQL Subquery from ASC order to DESC order

select *, sum(sales_qty) as total_qty
from sales_details
left join sales on sales.salesid=sales_details.salesid
where month(sales.sales_date)='$m'
group by productid order by total_qty asc limit 2, 4
I have that sql that is sorted in ascending order. Now I want the results to be sorted in descending order. I have tried using subquery but doesn't work for me. Any help or suggestion is appreciated.
This is the sql that I have tried:
select * from (
select *, sum(sales_qty) as total_qty
from sales_details
left join sales on sales.salesid=sales_details.salesid
where month(sales.sales_date)='$m'
group by productid
order by total_qty asc
limit 2, 4
) as sub
order by sum(sales_qty) desc
Your query with the subquery should end
... ORDER BY sales_qty DESC
Why? When you say ... ORDER BY SUM(sales_qty) DESC you're converting the outer query into an aggregate query. Because that outer aggregate query has no GROUP BY clause, it necessarily has a one row result set.
The outer query treats the inner query as if it were a table, a virtual table. That virtual table has a column named sales_qty. It is the value by which you want to order.
Pro tip: Don't use SELECT * in aggregate queries. You're misusing the notorious nonstandard MySQL extension to GROUP BY, which means your result set contains unpredictable values. Read this. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

In MySQL, what does this simple nested SELECT clause mean exactly?

Here is the example from this thread:
select (
select distinct Salary from Employee order by Salary Desc limit 1 offset 1
)as second;
The select(...) as second looks confusing to me because I've never seen a query-set instead of column names can be used as the argument of SELECT..
Does anyone have ideas about how to understand nested select clause like this? Is there any tutorials about this feature?
That's a subquery in the SELECT list of a query.
To get there, let's look at some other examples
SELECT t.id
, 'bar' AS foo
FROM mytable
WHERE ...
LIMIT ...
'bar' is just a string literal that gets returned in every row (in a column named foo) in the resultset from the query.
Also, MySQL allows us to run a query without a FROM clause
SELECT 'fee' AS fum
We can also put a subquery in the SELECT list of a query. For example:
SELECT t.id
, (SELECT r.id FROM resorts r ORDER BY r.id ASC LIMIT 1) AS id
FROM mytable
WHERE ...
LIMIT ...
The query pattern you asked about is a SELECT statement without a FROM clause
And the only expression being returned is the result from a subquery.
For example:
SELECT e.salary
FROM Employee e
GROUP BY e.salary
ORDER BY e.salary DESC
LIMIT 4,1
If this query runs, it will return one column, and will return either one or zero rows. (No more than one.) This satisfies the requirements for a subquery used in a SELECT list of another query.
SELECT ( subquery ) AS alias
With that, the outer query executes. There's no FROM clause, so MySQL returns one row. The resultset is going to consist of one column, with a name of "alias".
For each row returned by the outer query, MySQL will execute the subquery in the SELECT list. If the subquery returns a row, the value of the expression in the SELECT list of the subquery is assigned to the "alias" column of the resultset. If the execution of the subquery doesn't return a row, then MySQL assigns a NULL to the "alias" column.

MySQL sub-query issue

SELECT *
FROM (SELECT *
FROM content
WHERE topic='$id' AND active='1'
ORDER BY date DESC, id DESC
LIMIT 4) a
ORDER BY a.likes DESC
I have this query. I want it to select 4 entries from content table, and sort entries as follows:
SELECT most recent entries. It means ORDER BY date(mysql datetime) DESC, id DESC.
From those 4 selected, order them by likes(mysql INT) DESC
When runing my query, it returns wrong results. It selects entries matching this criteria WHERE topic='$id' AND active='1' . It sorts entries by likes DESC, but it ignore this criteria ORDER BY date DESC, id DESC, so it shows me results with a smaller id first.
What can be the reason? Thank you in advance
After OP edits, the correct query will be
SELECT *
FROM (SELECT *
FROM content
WHERE topic='$id' AND active='1'
ORDER BY date DESC, id DESC
LIMIT 4) a
ORDER BY a.likes DESC, date DESC, id DESC
The ORDER BY on the outermost query specifies the order of the rows returned. No other order of rows is guaranteed or implied.
From the original question (prior to the edit) sounds like OP wanted the rows returned in descending order by the integer value of the likes column. That is, OP wanted to specify:
ORDER BY a.likes DESC
on the outermost query.
The rows returned by the query will be returned in the sequence defined by ORDER BY on the outermost query. No other sequencing of rows is guaranteed.
If OP wants the rows returned in a specific order, then the list of expressions in the ORDER BY clause on the outermost query will need to be specified differently. For example:
ORDER BY a.likes DESC, a.date DESC, a.id DESC
--or--
ORDER BY a.date DESC, a.likes DESC, a.id DESC
The ORDER BY in the inline view will be honored by the inline view query; but once that inline view query is materialized, and is referenced as a row source by the outer query, that ORDER BY is gone. The outer query is free to access and return the rows from the inline view (derived table) in any order it wants; the outer query isn't required to honor the ORDER BY on the inline view query; the outer query just sees the derived table as a row set, like any other table.
(This is assuming that "likes" is a column in the content table, and not a result derived from some other table. We don't see what columns your query is returning, because you are using * as the SELECT list.)
(If that isn't what OP is looking for, OP can elaborate on the requirements for the specified resultset. Everything else looks right in OP query, for getting the four "latest" rows within the inline view.)
Try this:
SELECT *
FROM content
WHERE topic='$id' AND active='1'
ORDER BY date DESC, likes desc
LIMIT 4
You dont need another level of select to do order by.

COUNT(*) returning multiple rows instead of just one

Why does COUNT() return multiple rows when I just need the total count of how many rows my query generates?
Should return 1078.
The COUNT() is working as expected. When you put a group by clause, the count() gives you the result for GROUP BY. If you wish to get the count of rows in a query that includes group by, use it as a subquery instead.
Something like:
SELECT COUNT(*) FROM (SELECT * FROM `table`
GROUP BY `column1`) AS `a`
Well, simple answer. Don't GROUP BY if you don't need groups.
Either use COUNT(DISTINCT articles.company) without GROUP BY or keep the the GROUP BY and wrap the whole query in a SELECT COUNT(*) FROM (...) AS data, if you want to count the groups.
Do not use group by, it will count the number of each group.
Write the above query as subquery then it will give proper result and dont use group by
select count(*) from (select articles.id from 'contract_prices' left join 'articles' on
(arcticles.id = contract_prices.article)
where 'contract_to' >= curdate()
)