How to Group By after Order By without any aggregate function - mysql

I'm trying to get the unique records after sorting the data in specific order.
The data table looks like this
SELECT * FROM category_products;
Now, requirement is to Order By the records on category_id and then select unique rows of product_id. I wrote the below query to sort the records
SELECT * FROM category_products ORDER BY category_id=2 desc;
When I try to Group By this sorted results with product_id, then the results aren't in right order. Even tried Group By clause in both child query and same query.
SELECT * FROM
(SELECT
*
FROM
category_products
ORDER BY category_id = 2 DESC) AS cat_products
GROUP BY cat_products.product_id;
Current Output:
Expected Output:
The result isn't the right one for which I'm looking for. Kindly help me guys, this doesn't seems to that tricky thing but I'm kind of stuck with it.

requirement is to Order By the records on category_id and then select
unique rows of product_id. I wrote the below query to sort the records
This should be what you are looking for:
SELECT DISTINCT product_id
,(SELECT category_id
FROM category_products
WHERE product_id = CP.product_id
ORDER BY category_id
LIMIT 1) AS cat_id
FROM category_products CP;
you need a SUBQUERY with an ORDER BY and LIMIT 1

It's a little unclear on how you aim to achieve this but from my understanding you can maybe create a custom sorting column to fulfill your requirement. See example below:
SELECT *,
CASE WHEN category_id=2 THEN 1
WHEN category_id=4 THEN 2
ELSE 99 END AS rownum
FROM category_products
ORDER BY rownum, product_id;
I'm using CASE to define a custom rownum and use it in the ORDER BY clause.
Demo fiddle here: https://www.db-fiddle.com/f/kAcGYtng2RWCf2Yhn5N1C9/0

Related

how to get first value of duplicate value in mysql

I have a table where I am having duplicates value also.
From that table, I want to get the first value of duplicate values via an order by id desc.
I am using below query to find count
select product_sku, quantity
from catalog_product_store_inventory
where ax_store_id=999
ORDER BY id DESC;
From this query, I get the all duplicates value.
I hope I made my query clear.
I am very new to MySQL.
What means duplicates in your case? Duplicates according to what product_sku or both product_sku,quantity - this should be used in GROUP BY clause:
SELECT product_sku,quantity
FROM catalog_product_store_inventory c
JOIN (
SELECT MAX(id) id
FROM catalog_product_store_inventory
GROUP BY product_sku
) m ON c.id = m.id
ORDER BY id DESC means that you want last ID from group and this one is MAX.

MySQL 5.7 How to do GROUP BY with sorting?

Similar to this issue: MySQL 5.7 group by latest record
I'm not sure how to do this properly in 5.7. Also with possibility of 2nd sort column. Working query in 5.6 that I'm trying to replicate in 5.7:
SELECT id FROM test
GROUP BY category
ORDER BY sort1 DESC, sort2 DESC
id is not always the highest, so MAX(id) does not work.
Looking into the link above, the solution for single sort should be:
SELECT t1.*
FROM test t1
INNER JOIN (
SELECT category, max(sort) AS sort FROM test GROUP BY category
) t2 ON t2.category = t1.category AND t2.sort = t1.sort
But how will it work with 2 sorting?
You are using GROUP BY the wrong way.
Think of group by as a way to separate data row into different groups. Each group has multiple rows, based on the value of group by column.
Once you get those groups, selecting table columns (as in: select *) is like picking any row from that group randomly. This is not helpful nor useful.
Usually once we group records (or rows), we need to find meta information about those records. For example: get us the count of records in that group (as in: select count(*)), or the sum of values of a specific column in that group (as in: select sum(price)), or get the min, max or avg values.
So in a nutshell, when you use group by you should use on of the aggregation functions with it, otherwise it's not going to do you any good.
Why don't you have the ORDER BY at your outer query, instead?
SELECT *
FROM (
SELECT 100 AS id, 1 AS category, NULL AS sort
UNION
SELECT 200 AS id, 1 AS category, 2 AS sort
) dt
GROUP BY category
ORDER BY sort DESC;
It seems that what happened to the data when it was grouped, it took the first data while neglecting the ORDER BY DESC. On your first query, it ordered descending first then group by took the first record which is 200. And yes, this shouldn't be the way you should use GROUP BY. It is used in conjunction with aggregate functions.
when you select a column in a group by query that is not one of the columns you are grouping by, (ie, your id) you have no control over the value unless you use another aggregate function. If you want to sort, use MIN or MAX:
SELECT MAX(id), category, FROM `test2`
GROUP BY category; -- always returns 200
SELECT MIN(id), category, FROM `test2`
GROUP BY category; -- always returns 100

Why the result not fit when I run group by and order by?

My query like this :
SELECT *
FROM products_categories
WHERE product_id = 1
ORDER BY updated_at DESC
If the query run, the result like this :
I add group by like this :
SELECT *
FROM products_categories
WHERE product_id = 1
GROUP BY product_id
ORDER BY updated_at DESC
The result : display 1 record (id=1)
It does not fit. Should the id shown is id = 3 (latest updated_at)
How can I solve it?
Unfortunately you are trapped by the strange behavior of mysql (some other sql engines like sqlite do the same). Your sql query is not correct according to sql98 and should be yield an error. You can not select fields which are not grouped for or using aggregate function (max/min/avg). Unfortunately mysql wont yield an error but gives back the first value for the ill defined fields.
The group by will merge all your rows with the same product_id into single row. That's why you get 1 (wrong) line back. I suppose you thought the order by will run first before the group by. This is not the case. The single (grouped by) row will be sorted.
If you want to get the latest updated_at, you should query that:
select max(updated_at) from products_categories WHERE product_id = 1 and then query the row which using this value in an another select. (select * from products_categories where product_id=1 and updated_at = (select max(updated_at) from products_categories where products_id=1)) Of course it may not work as intended if your updated_at value is not unique. Then you will get multiple results.
If you need strictly one answer row you can do
SELECT * FROM products_categories
WHERE product_id = 1 ORDER BY updated_at DESC LIMIT 1;

MySQL: First select 10 newest rows in descending PK order, then the rest of records alphabetically

I have a simple table USERS:
id | name
----+------
Can you help me with the query that would fetch all rows from the table and:
a) Place 10 rows with highest PK values on top, in id DESC order;
b) Place all remaining rows ordered by name ASC order.
Thank you!
This is a bit of a tricky question. The approach I would take is a join approach. Identify the primary keys for the first group using a join (this is happily fast because you are working with primary keys). Then use the match to that table for the order by:
select t.*
from table t left outer join
(select id
from table t
order by id desc
limit 10
) t10
on t.id = t10.id
order by t10.id desc,
t.name asc;
First question would be: do you really need this in one single query? I'm really not seeing the use case for such a query to be honest.
It'd be easier to just fetch the 10 biggest ids (storing somewhere the 10th biggest), and then fetch the rest in ascending name order (with a restriction on ids being smaller than the 10th biggest).
Otherwise in a single query, something like this would work, but it doesn't seem very efficient to me (maybe someone will have a better idea).
(
SELECT
id, name
from
USERS
ORDER BY id DESC LIMIT 0,10
)
UNION
(
SELECT
id, name
from
USERS
WHERE
id NOT IN (
SELECT id, name from USERS ORDER BY id DESC LIMIT 0,10
)
ORDER BY name ASC
)
(or maybe with a NOT EXISTS - the inner query will be different - instead of the NOT IN)

Get biggest COUNT(DISTINCT) with condition mysql

right now I'm trying to return the biggest COUNT(DISTINCT column)-number from a mysql table.
It's hard to describe, so I'll give you an example:
My table has the following columns: s_id, k_id, p_id.
Now I want to count the different s with the condition that every entry has the same p_id, too. I need this to prepare a HTML-Table (so i know how many Columns this table will have).
Data Example:
This is what I got, so far:
SELECT COUNT(DISTINCT k_id) AS a FROM `table`
the problem with this is, that there may be 4 different k_ids but 3 of them are related to p_id = 1 and the last one is releated to p_id = 2.
a returns 4 instead of 3.
Thanks for support!
I think you want this:
select p_id, count(distinct s_id) as cnt
from table
group by p_id
order by cnt desc
limit 1;
Please consider this:
select max(count(distinct(k_id))) from table
group by p_id