specify order in order BY - mysql

this is a simple question but I have been googling long time now but no results.
SELECT * FROM `target` WHERE `week_id`=23
and `ini_id`=2
ORDER BY `region_id`
When I order this query it is either in ASC or DESC.
Can I specify a sequence for region_id like (5,6,7,1,2,3,4)

You can use FIELD for that:
SELECT *
FROM `target`
WHERE `week_id`= 23
and `ini_id`= 2
ORDER BY FIELD(`region_id`,5,6,7,1,2,3,4)

You should be able to use FIND_IN_SET:
SELECT *
FROM `target`
WHERE `week_id`=23
and `ini_id`=2
ORDER BY FIND_IN_SET(`region_id`, '5,6,7,1,2,3,4')

Not directly, no, but you can get the resultset ordered per the specification d using an expression, such as:
ORDER BY CASE WHEN region_id IN (5,6,7) THEN 1 ELSE 2 END, region_id
That CASE expression is deriving a value from the region_id. So rows with a region_id of 5, 6 or 7 get assigned a value of "1", and all other rows get assigned a "2". When we order by that, all the 5,6,7 region_id rows come first, then everything else.
The next step is to then order by the region_id.

Two ways to do this:
Order by Calculated
You could do order by, but with a calculated value so that you get the order you want.
For example:
select * from data order by (region_id+5)%10;
SQL Fiddle: http://www.sqlfiddle.com/#!2/5f80da/2
Using Union
(select * from data where region_id > 4)
UNION
(select * from data where region_id < 5)
SQL Fiddle: http://www.sqlfiddle.com/#!2/09fe1/1

Related

How can I select the row from a table whose 1 field is maximum or minimum?

In my table I have a field name rt_stars which includes integer anyone between 1 to 5. Suppose there are 5 rows having rt_stars 4,4,3,2,1 respectively. Here, 4 is the highest and 1 is the lowest. If I want to select the row with the maximum value 4 how can I do that? Since there are two 4 here the last one will be selected. Can I have query something like this?
SELECT * FROM ratings WHERE MAX(rt_stars) ORDER BY rt_id DESC LIMIT 1
I know this is wrong but that's how I want to select all the values from the rows if the rt_stars field has the maximum value in it. How can I achieve this kind of a query?
You can select one row using:
select r.*
from ratings r
order by rt_stars desc, rt_id desc
limit 1;
The problem with your query is that you cannot use max() in the where clause. Beyond that, you don't need aggregation at all -- just ordering the rows and then selecting the first one.
If you want all rows with the maximum stars you can do:
select *
from ratings
where rt_stars = (select max(rt_stars) from ratings)
If you just want one of them randomly you can do:
select *
from ratings
order by rt_stars desc
limit 1
I think the below SQL code will help.
SELECT * FROM ratings WHERE rt_stars = MAX(rt_stars) ORDER BY rt_id DESC;
Sorry the code modified below
SELECT * FROM ratings WHERE rt_stars = ( SELECT MAX( user_05_pk ) FROM ratings )
ORDER BY rt_id DESC;

Will DISTINCT always return a same order of values for a same SQL?

I have a sql statement is with pattern
SELECT id FROM table WHERE [conditions] ORDER BY [orders] LIMIT 10000 OFFSET 0
and the return value is like below:
id
-----
1
0
0
0
0
1
1
1
2
2
...
Then I want to get the distinct value as the order of their first appearance, since there's an ORDER BY in the sql, and DISTINCT or GROUP BY are both happened before ORDER BY in a sql, I tried below sql.
SELECT DISTINCT id FROM (SELECT id FROM table WHERE [conditions] ORDER BY [orders] LIMIT 10000 OFFSET 0) tmp;
And the result is like what I want:
id
----
1
0
2
...
My question is: can I ensure that in a same pattern SQL, DISTINCT will always return the distinct id as the order their first appearance?
Thanks.
---------------Notes------------------
Below can be ignored. I just noticed many peoples are recommended to try GROUP BY, so I tried below sql as well:
SELECT id FROM (SELECT id FROM table WHERE [conditions] ORDER BY [orders] LIMIT 10000 OFFSET 0) tmp GROUP BY id;
but the returning is reordered by the alpha-beta order (it's not integer order because the column is a CHAR column for the real id is a string), which is not what I want.
id
----
0
1
10
100
....
If you want results in a particular order, then you need to specify that in the ORDER BY for the outermost SELECT. That suggests something like this:
SELECT id
FROM tabl
WHERE [conditions]
ORDER BY [orders]
LIMIT 10000 OFFSET 0
Then, if you want to order by the first appearance, you need a column that specifies the first appearance. Let's call this CreatedAt (perhaps it is orders?). If so:
SELECT id
FROM table
WHERE conditions
GROUP BY id
ORDER BY min(CreatedAt)
LIMIT 10000;
Note: SQL tables represent unordered sets, so you need a column to specify the ordering of interest.

MySQL wrong results with GROUP BY and ORDER BY

I have a table user_comission_configuration_history and I need to select the last Comissions configuration from a user_id.
Tuples:
I'm trying with many queries, but, the results are wrong. My last SQL:
SELECT *
FROM(
SELECT * FROM user_comission_configuration_history
ORDER BY on_date DESC
) AS ordered_history
WHERE user_id = 408002
GROUP BY comission_id
The result of above query is:
But, the correct result is:
id user_id comission_id value type on_date
24 408002 12 0,01 PERCENTUAL 2014-07-23 10:45:42
23 408002 4 0,03 CURRENCY 2014-07-23 10:45:41
21 408002 6 0,015 PERCENTUAL 2014-07-23 10:45:18
What is wrong in my SQL?
This is your query:
SELECT *
FROM (SELECT *
FROM user_comission_configuration_history
ORDER BY on_date DESC
) AS ordered_history
WHERE user_id = 408002
GROUP BY comission_id;
One major problem with your query is that it uses a MySQL extension to group by that MySQL explicitly warns against. The extension is the use of other columns in the in theselect that are not in the group by or in aggregation functions. The warning (here) is:
MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause. This means
that the preceding query is legal in MySQL. You can use this feature
to get better performance by avoiding unnecessary column sorting and
grouping. However, this is useful primarily when all values in each
nonaggregated column not named in the GROUP BY are the same for each
group. The server is free to choose any value from each group, so
unless they are the same, the values chosen are indeterminate.
So, the values returned in the columns are indeterminate.
Here is a pretty efficient way to get what you want (with "comission" spelled correctly in English):
SELECT *
FROM user_commission_configuration_history cch
WHERE NOT EXISTS (select 1
from user_commission_configuration_history cch2
where cch2.user_id = cch.user_id and
cch2.commission_id = cch.commission_id and
cch2.on_date > cch.on_date
) AND
cch.user_id = 408002;
Here's one way to do what your trying. It gets the max date for each user_ID and commissionID and then joins this back to the base table to limit the results to just the max date for each commissionID.
SELECT *
FROM user_comission_configuration_history A
INNER JOIN (
SELECT User_ID, Comission_Id, max(on_Date) mOn_Date
FROM user_comission_configuration_history
Group by User-Id, Comission_Id
) B
on B.User_ID = A.User_Id
and B.Comission_Id = A.Comission_ID
and B.mOnDate=A.on_date
WHERE user_id = 408002
ORDER BY on_Date desc;

Find most frequent value in SQL column

How can I find the most frequent value in a given column in an SQL table?
For example, for this table it should return two since it is the most frequent value:
one
two
two
three
SELECT
<column_name>,
COUNT(<column_name>) AS `value_occurrence`
FROM
<my_table>
GROUP BY
<column_name>
ORDER BY
`value_occurrence` DESC
LIMIT 1;
Replace <column_name> and <my_table>. Increase 1 if you want to see the N most common values of the column.
Try something like:
SELECT `column`
FROM `your_table`
GROUP BY `column`
ORDER BY COUNT(*) DESC
LIMIT 1;
Let us consider table name as tblperson and column name as city. I want to retrieve the most repeated city from the city column:
select city,count(*) as nor from tblperson
group by city
having count(*) =(select max(nor) from
(select city,count(*) as nor from tblperson group by city) tblperson)
Here nor is an alias name.
Below query seems to work good for me in SQL Server database:
select column, COUNT(column) AS MOST_FREQUENT
from TABLE_NAME
GROUP BY column
ORDER BY COUNT(column) DESC
Result:
column MOST_FREQUENT
item1 highest count
item2 second highest
item3 third higest
..
..
For use with SQL Server.
As there is no limit command support in that.
Yo can use the top 1 command to find the maximum occurring value in the particular column in this case (value)
SELECT top1
`value`,
COUNT(`value`) AS `value_occurrence`
FROM
`my_table`
GROUP BY
`value`
ORDER BY
`value_occurrence` DESC;
Assuming Table is 'SalesLT.Customer' and the Column you are trying to figure out is 'CompanyName' and AggCompanyName is an Alias.
Select CompanyName, Count(CompanyName) as AggCompanyName from SalesLT.Customer
group by CompanyName
Order By Count(CompanyName) Desc;
If you can't use LIMIT or LIMIT is not an option for your query tool. You can use "ROWNUM" instead, but you will need a sub query:
SELECT FIELD_1, ALIAS1
FROM(SELECT FIELD_1, COUNT(FIELD_1) ALIAS1
FROM TABLENAME
GROUP BY FIELD_1
ORDER BY COUNT(FIELD_1) DESC)
WHERE ROWNUM = 1
If you have an ID column and you want to find most repetitive category from another column for each ID then you can use below query,
Table:
Query:
SELECT ID, CATEGORY, COUNT(*) AS FREQ
FROM TABLE
GROUP BY 1,2
QUALIFY ROW_NUMBER() OVER(PARTITION BY ID ORDER BY FREQ DESC) = 1;
Result:
Return all most frequent rows in case of tie
Find the most frequent value in mysql,display all in case of a tie gives two possible approaches:
Scalar subquery:
SELECT
"country",
COUNT(country) AS "cnt"
FROM "Sales"
GROUP BY "country"
HAVING
COUNT("country") = (
SELECT COUNT("country") AS "cnt"
FROM "Sales"
GROUP BY "country"
ORDER BY "cnt" DESC,
LIMIT 1
)
ORDER BY "country" ASC
With the RANK window function, available since MySQL 8+:
SELECT "country", "cnt"
FROM (
SELECT
"country",
COUNT("country") AS "cnt",
RANK() OVER (ORDER BY COUNT(*) DESC) "rnk"
FROM "Sales"
GROUP BY "country"
) AS "sub"
WHERE "rnk" = 1
ORDER BY "country" ASC
This method might save a second recount compared to the first one.
RANK works by ranking all rows, such that if two rows are at the top, both get rank 1. So it basically directly solves this type of use case.
RANK is also available on SQLite and PostgreSQL, I think it might be SQL standard, not sure.
In the above queries I also sorted by country to have more deterministic results.
Tested on SQLite 3.34.0, PostgreSQL 14.3, GitHub upstream.
Most frequent for each GROUP BY group
MySQL: MySQL SELECT most frequent by group
PostgreSQL:
Get most common value for each value of another column in SQL
https://dba.stackexchange.com/questions/193307/find-most-frequent-values-for-a-given-column
SQLite: SQL query for finding the most frequent value of a grouped by value
SELECT TOP 20 WITH TIES COUNT(Counted_Column) AS Count, OtherColumn1,
OtherColumn2, OtherColumn3, OtherColumn4
FROM Table_or_View_Name
WHERE
(Date_Column >= '01/01/2023') AND
(Date_Column <= '03/01/2023') AND
(Counted_Column = 'Desired_Text')
GROUP BY OtherColumn1, OtherColumn2, OtherColumn3, OtherColumn4
ORDER BY COUNT(Counted_Column) DESC
20 can be changed to any desired number
WITH TIES allows all ties in the count to be displayed
Date range used if date/time column exists and can be modified to search a date range as desired
Counted_Column 'Desired_Text' can be modified to only count certain entries in that column
Works in INSQL for my instance
One way I like to use is:
select *<given_column>*,COUNT(*<given_column>*)as VAR1 from Table_Name
group by *<given_column>*
order by VAR1 desc
limit 1

GROUP BY after ORDER BY

I need to do GROUP BY after ORDER BY. I don't understand why MySQL doesn't support that.
This is my code:
SELECT
`pages`.`id`,
`contents`.`id_language`,
[...]
[...]
ORDER BY
FIND_IN_SET(`languages`.`id`, '3') DESC
[the GROUP BY]
The results will be something like this:
id | id_language | ...
1 3
1 1
2 3
2 5
2 1
I need to group by ID, I need only the first result and I need to save in a view. I can't use a SUBQUERY because of that.
The result need to be:
id | id_language | ...
1 3
2 3
Note: Don't get confused by id_language = 3, because it isn't a rule.
SELECT id, idl
FROM (SELECT
`pages`.`id` as id,
`contents`.`id_language` as idl,
[...]
[...]
ORDER BY
FIND_IN_SET(`languages`.`id`, '3') DESC
) d
GROUP BY d.id
Group By will group result sets, and is generally used for aggregation.
Order By is the way that results are sorted.
You may want an additional column in your original query that you GROUP BY, along with whatever you're currently grouping by. That column, when grouped, could then be used to order afterward. For instance:
SELECT
SUM(IF(`languages`.`id` = 3, 1, 0)) AS languageOrder,
`pages`.`id`,
`contents`.`id_language`,
[...]
[...]
[GROUP BY...]
ORDER BY languageOrder DESC
I would intend for languageOrder to be positive for groups that contain language #3, 0 otherwise. So groups that contain language 3 will be at the top.
Very amusing, try
select * from your_table
where id_language=3
order by id;
As far I can tell, the rule set is id_language=3,
which make no differences from using where