MySQL Subquery from ASC order to DESC order - mysql

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

Related

MySQL Row more appear with multiple row same result

I have a query with a count with some group by, and I want to get the greater count. I can do with an order by and limit 1, but I have multiple results with the same count and then does not work for me.
How do I solve this problem?
With MySql 8+, you can use CTE to get the maximum count, and then retrieve all records with a count equal to the maximum count.
However, since CTE is not available in MySql 5.6, you'd need to use a sub-query to get the maximum count, and then write the main query which compares the count of each record to the maximum count retrieved in the subquery.
Here is a query I wrote. Maybe it's not the most efficient solution, but it gets the desired result.
SELECT
group_id, COUNT(record_id) c
FROM
table_name
GROUP BY group_id
HAVING c IN (
SELECT
MAX(sub_query.c)
FROM
(SELECT
group_id, COUNT(record_id) c
FROM
table_name
GROUP BY group_id) AS sub_query
)
If you are not going to do this using window functions, you can do:
SELECT group_id, COUNT(*) as cnt
FROM table_name
GROUP BY group_id
HAVING cnt = (SELECT COUNT(*)
FROM table_name
GROUP BY group_id
ORDER BY COUNT(*) DESC
LIMIT 1
) ;

Do I need inner ORDER BY when there is an outer ORDER BY?

Here is my query:
( SELECT id, table_code, seen, date_time FROM events
WHERE author_id = ? AND seen IS NULL
) UNION
( SELECT id, table_code, seen, date_time FROM events
WHERE author_id = ? AND seen IS NOT NULL
LIMIT 2
) UNION
( SELECT id, table_code, seen, date_time FROM events
WHERE author_id = ?
ORDER BY (seen IS NULL) desc, date_time desc -- inner ORDER BY
LIMIT 15
)
ORDER BY (seen IS NULL) desc, date_time desc; -- outer ORDER BY
As you see there is an outer ORDER BY and also one of those subqueries has its own ORDER BY. I believe that ORDER BY in subquery is useless because final result will be sorted by that outer one. Am I right? Or that inner ORDER BY has any effect on the sorting?
Also my second question about query above: in reality I just need id and table_code. I've selected seen and date_time just for that outer ORDER BY, Can I do that better?
You need the inner order by when you have a limit in the query. So, the third subquery is choosing 15 rows based on the order by.
In general, when you have limit, you should be using order by. This is particularly true if you are learning databases. You might seem to get the right answer -- and then be very surprised when it doesn't work at some later point in time. Just because something seems to work doesn't mean that it is guaranteed to work.
The outer order by just sorts all the rows returned by the subqueries.

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.

How to query distinct records in mysql

Hi I want to query unique records using distinct in mysql but the problem is that it only returns a single column, how can I make it return all?
Here's my initial query:
SELECT distinct(country_name)
FROM HST_LOCATION
WHERE person_id='1897'
ORDER BY date_updated DESC
group by country_name
The GROUP BY clause makes that column distinct, there's no need to use the DISTINCT modifier. Just select all the columns and you should get what you want.
SELECT *
FROM HST_LOCATION
WHERE person_id = '1897'
GROUP BY country_name
ORDER BY date_updated DESC

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()
)