Having both GROUP BY and ORDER BY in one query - mysql

I've been told that I can't have GROUP BY and ORDER BY in one MySQL Query. Here is an abbreviated version of the query -
SELECT n.colorName, n.colorComp, n.colorID, SUM(n.gallons) AS TotalGallons
FROM netTran n, Store m, Product p
WHERE ((n.store = m.store) and m.state = "FL")
AND ((n.salesNbr = p.salesNbr) AND (p.intExt = "EXTERIOR" OR p.intExt = "INT/EXT"))
AND ((n.clrnt1 = "L1") AND (n.clrnt1 = "R3"))
GROUP BY n.colorComp, n.colorID
ORDER BY TotalGallons DESC;
I've been told that having the ORDER BY with the GROUP BY will give me different results and that the only way the ORDER BY would work is if the main query were nested in
SELECT * FROM
(query)
ORDER BY TotalGallons DESC;
Is that correct?

Use the query as
SELECT n.colorName, n.colorComp, n.colorID, SUM(n.gallons) AS TotalGallons
FROM netTran n, Store m, Product p
WHERE ((n.store = m.store) and m.state = "FL")
AND ((n.salesNbr = p.salesNbr) AND (p.intExt = "EXTERIOR" OR p.intExt = "INT/EXT"))
AND ((n.clrnt1 = "L1") AND (n.clrnt1 = "R3"))
GROUP BY n.colorName, n.colorComp,n.colorID
ORDER BY TotalGallons DESC;
You can have grouo by and order by in a single query. But you need to provide all columns in case of you are aggregating a column

Group by will change the results.. Order by will just present data in order..
Having the ORDER BY with the GROUP BY won't give you different results

Yes, that's true. In the mysql reference manual you can read th
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:
I suppose that this means that ORDER BY has no effect at all.
Curious... I always thought that order by worked...

GROUP BY and ORDER BY are two different things. It is plain wrong that you cannot use them together.
GROUP BY is used to tell the DBMS per which group to aggregate the data. In your example you sum gallons per colorComp and colorID.
ORDER BY is used to tell the DBMS in which order you want the data shown. In your query by the sum of gallons descending.
In standard SQL you don't usually use GROUP BY without ORDER BY, because in spite of the grouping, the data may be shown unordered. MySQL however decided to guarantee that GROUP BY performs an ORDER BY. So in MySQL it was not necessary to use ORDER BY after GROUP BY, as long as you didn't want another order as in your example. This non-standard behavior is now deprecated. See here:
https://dev.mysql.com/doc/refman/5.6/en/group-by-optimization.html
However, relying on implicit GROUP BY sorting is deprecated.
So you should have an ORDER BY clause now whenever you want data sorted. With no exception.

Related

Why am I getting a syntax error in MySQL when I used Group By?

Why am I getting an error on the last line?
SELECT
*
FROM
datawarehouse.shipments
WHERE
ControlBranch = 'SFO'
AND ShipmentCreateDateUTC >= '2020-03-01'
ORDER BY id DESC
GROUP BY ShipmentNumber;
What I'm trying to accomplish is order by id Desc, Group by ShipmentNumber, and then pull all the fields.
Well, first of all the query won't work because you are grouping something, and then showing everything with an * syntax. You need to show the column that you are grouping and then use aggregating functions with the rest (SUM, COUNT, AVG, etc) so it shows the value grouped.
After that, you need to check the instruction order that SQL Server uses. The Order by goes always at the end of the instructions. So, the correct order of your query is like this:
SELECT id, COUNT(*) -- The count is an example
FROM datawarehouse.shipments
WHERE
ControlBranch = 'SFO'
AND ShipmentCreateDateUTC >= '2020-03-01'
GROUP BY ShipmentNumber
ORDER BY id DESC;
Also, even if it's not relevant, you can have a better understanding of how the engine works behind the curtain (the order of execution) checking this link:
https://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/

MySQL ORDER BY from subquery lost by GROUP BY

I have a table x :
id lang externalid
1 nl 10
2 nl 11
3 fr 10
From this table I want al the rows for a certain lang and externalid, if the externalid doesn't exist for this lang, I want the row with any other lang.
The subquery sorts the table correct, but when I add the group by, the sort of the subquery is lost. This works in older mysql versions but not in 5.7.
(
SELECT
*
FROM
x
ORDER BY FIELD(lang, "fr") DESC, id
)
as y
group by externalid
I want the query to return the records with id 2 & 3. So for each distinct external id, if possible the lang = 'fr', else any other lang.
How can i solve this problem?
You are talking of given externalid and land. No need to group by externalid hence; use a mere where clause instead.
Combined with ORDER BY and LIMIT you get the record you want (i.e. the desired language if such a record exists, else another one).
select *
from mytable
where externalid = 10
order by lang = 'fr' desc
limit 1;
UPDATE: Okay, according to your comment you want to get the "best" record per externalid. In standard SQL you'd use ROW_NUMBER for this. Other DBMS have further solutions, e.g. Oracle's KEEP FIRST or Postgre's DISTINCT ON. MySQL doesn't support any of these. One way would be to emulate ROW_NUMBER with variables. Another would be to use above query as a subquery per externalid to find the best records:
select *
from mytable
where id in
(
select
(
select m.id
from mytable m
where m.externalid = e.externalid
order by m.lang = 'fr' desc
limit 1
) as best_id
from (select distinct externalid from mytable) e
);
Your subquery generates a result set (a virtual table) that's passed to your outer query.
All SQL queries, without exception, generate their results in unpredictable order unless you specify the order completely in an ORDER BY clause.
Unpredictable is like random, except worse. Random implies you'll get a different order every time you run the query. Unpredictable means you'll get the same order every time, until you don't.
MySQL ordinarily ignores ORDER BY clauses in subqueries (there are a few exceptions, mostly related to subquery LIMIT clauses). Move your ORDER BY to the top level query.
Edit. You are also misusing MySQL's notorious nonstandard extension to GROUP BY.

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.

Order by Date not working as expected in MySql

I have a mysql query
select count(*) as TotalCount,
pd.Product_Modified_Date,
psc.Product_Subcategory_Name,
pd.Product_Image_URL
from product_subcategory psc
inner join product_details pd on psc.Product_Subcategory_ID = pd.Product_Subcategory_Reference_ID
where pd.Product_Status = 0 and
psc.Product_Subcategory_Status = 0
group by psc.Product_Subcategory_Name
order by pd.Product_Modified_Date desc
In my product_details table have new image urls. But i could not get it by the above query.
How can i do it?
You are grouping by one column, Product_Subcategory_Name, but you have other columns Product_Image_URL and Product_Modified_Date in your select-list.
If you have cases where the group has multiple rows (which you do, since the count is 14 or more in each group), MySQL can only present one value for the Product_Image_URL. So it picks some row in the group, and uses the value in that row. The URL value for all other rows in the group is ignored.
To fix this, you must group by all columns in your select-list that are not part of an aggregate function. Any column you don't want to use to form a new group must go into an aggregate function.
Roland Bouman wrote an excellent blog detailing how to use GROUP BY properly: http://rpbouman.blogspot.com/2007/05/debunking-group-by-myths.html
Combining GROUP BY and ORDER BY is problematic and your problem is most likely covered in another question on Stack Exchange : MySQL wrong results with GROUP BY and ORDER BY

Conditional Distinct in MYSQL with respect o another column

I have query as follow
SELECT * FROM content_type_product cp
JOIN content_field_product_manufacturer cf ON cf.nid = cp.nid group by cp.nid
ORDER
BY field(cf.field_product_manufacturer_value,'12') DESC,
cp.field_product_price_value DESC
This is working perfect just a small flaw, there are two records having the same id (one is for cf.field_product_manufacturer_value='12' and other is for cf.field_product_manufacturer_value = '57') which I eliminated using group by clause. But the problem is that I want to get that particular id which has greater "field_product_price_value" but somehow it gives me the value which is lesser. If I query it for '57' then it gives me the id with greater field_product_price_value but when I query it for '12' it gives me id for lesser "field_product_price_value". Is there any way where I can specify to pick the id with greater "field_product_price_value"
You should use max(field_product_price_value) combined with appropriate GROUP BY-clause.
In general, you should use GROUP BY-clause only when you select both normal columns and aggregate functions (MIN, MAX, COUNT, AVG) in the query.
You query is using a (mis)feature of MySQL called Hidden Columns. This is only advised when all the unaggregated columns in the SELECT and not in the GROUP BY have the same value. This is not the case, so you need to select the correct records yourself:
SELECT cp.*, cf.*
FROM content_type_product cp JOIN
content_field_product_manufacturer cf
ON cf.nid = cp.nid join
(select cf.nid, max(field_product_price_value) as maxprice
from content_field_product_manufacturer
group by cf.nid
) cfmax
on cf.nid = cfmax.nid and cf.field_product_price_value = cfmax.maxprice
ORDER BY field(cf.field_product_manufacturer_value,'12') DESC,
cp.field_product_price_value DESC
Unless you really know what you are doing, when you use a GROUP BY, be sure all unaggregated columns in the SELECT are in the GROUP BY.
'2' > '12'
if we are talking about varchars. I believe you should convert your field to number type and your sort will work fine. Read this article for more information.