How can I sort by multiple columns in SQL and in different directions. column1 would be sorted descending, and column2 ascending.
ORDER BY column1 DESC, column2
This sorts everything by column1 (descending) first, and then by column2 (ascending, which is the default) whenever the column1 fields for two or more rows are equal.
The other answers lack a concrete example, so here it goes:
Given the following People table:
FirstName | LastName | YearOfBirth
----------------------------------------
Thomas | Alva Edison | 1847
Benjamin | Franklin | 1706
Thomas | More | 1478
Thomas | Jefferson | 1826
If you execute the query below:
SELECT * FROM People ORDER BY FirstName DESC, YearOfBirth ASC
The result set will look like this:
FirstName | LastName | YearOfBirth
----------------------------------------
Thomas | More | 1478
Thomas | Jefferson | 1826
Thomas | Alva Edison | 1847
Benjamin | Franklin | 1706
SELECT *
FROM mytable
ORDER BY
column1 DESC, column2 ASC
Multiple column ordering depends on both column's corresponding values:
Here is my table example where are two columns named with Alphabets and Numbers and the values in these two columns are asc and desc orders.
Now I perform Order By in these two columns by executing below command:
Now again I insert new values in these two columns, where Alphabet value in ASC order:
and the columns in Example table look like this.
Now again perform the same operation:
You can see the values in the first column are in desc order but second column is not in ASC order.
You can use multiple ordering on multiple condition,
ORDER BY
(CASE
WHEN #AlphabetBy = 2 THEN [Drug Name]
END) ASC,
CASE
WHEN #TopBy = 1 THEN [Rx Count]
WHEN #TopBy = 2 THEN [Cost]
WHEN #TopBy = 3 THEN [Revenue]
END DESC
SELECT id,
first_name,
last_name,
salary
FROM employee
ORDER BY salary DESC, last_name;
If you want to select records from a table but would like to see them sorted according to two columns, you can do so with ORDER BY. This clause comes at the end of your SQL query.
After the ORDER BY keyword, add the name of the column by which you’d like to sort records first (in our example, salary). Then, after a comma, add the second column (in our example, last_name). You can modify the sorting order (ascending or descending) separately for each column. If you want to use ascending (low to high) order, you can use the ASC keyword; this keyword is optional, though, as that is the default order when none is specified. If you want to use descending order, put the DESC keyword after the appropriate column (in the example, we used descending order for the salary column).
SELECT * FROM EMP ORDER BY DEPTNO ASC, JOB DESC;
TRY
'select * FROM users ORDER BY id DESC, name ASC, age DESC
You can also sort or order by the Number of Characters in each Column you wish to sort by. Shown below is a sample which sorts by the first three characters of the First Name and by the last two characters in the name of the town.
SELECT *
FROM table_name
ORDER BY LEFT(FirstName, 3) ASC, LEFT(Town, 2);
Related
I have a mysql table with entries of my driver's logbook. In the table there are two columns: start_place and end_place. Sometimes it's possible, that end_place is equal to start_place (i think that sounds logical).
Now I wan't to select the entries of the table which occour as tupel (x,y), but not as (y,x).
Example:
id | start_place | end_place
-----------------------------------
0 | New York | San Francisco
-----------------------------------
1 | San Francisco | New York
The row with the id 1 is a duplicate of id 0 in reversed order and should not be part of the result.
Does someone has an idea? Several times I tried with subselects or where conditions like (x,y) != (y,x) but that doesn't work.
This can be done with least and greatest functions with a group by.
select least(start_place,end_place), greatest(start_place,end_place)
from tbl
group by least(start_place,end_place), greatest(start_place,end_place)
having count(*) = 1
To retrieve such rows with other columns, use
select *
from tbl
where (least(start_place,end_place), greatest(start_place,end_place))
in (select least(start_place,end_place), greatest(start_place,end_place)
from tbl
group by least(start_place,end_place), greatest(start_place,end_place)
having count(*) = 1
)
Use LEAST, GREATEST and DISTINCT to get distinct pairs:
select distinct
least(start_place, end_place) as place1,
greatest(start_place, end_place) as place2
from mytable;
suppose there is a table
id desc
1 a
1 b
1 c
1 a
2 a
2 a
what I want to do is to show a mix of desc if the desc under the same id are different, otherswise show the value of the desc. Just like below
id desc
1 a/b/c
2 a
How could I do it in one sql ?
enter code here
I think you want group_concat() with the distinct modifier:
select id, group_concat(distinct `desc` separator '/') as `desc`
from t
group by id;
Note that desc is a bad name for a column because it is a SQL keyword (think order by). It is best to avoid grammatical elements when choosing names.
In my application, each product group has many products, and each product has one manufacturer. These relations are stored by MySQL in InnoDB tables product_groups with an id field, and products with id, product_group and manufacturer fields.
Is there a way to find the most common manufacturer in each product group, without resorting to selecting subqueries?
This is how I'm doing it currently:
SELECT product_groups.id,
(
SELECT manufacturer FROM products
WHERE product_group = product_groups.id
GROUP BY manufacturer
ORDER BY count(*) DESC
LIMIT 1
) manufacturer_mode
FROM product_groups;
Try this solution:
SELECT
a.product_group,
SUBSTRING_INDEX(GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'), ':::', 1) AS manufacturer_mode
FROM
(
SELECT
aa.product_group,
aa.manufacturer,
COUNT(*) AS occurrences
FROM
products aa
GROUP BY
aa.product_group,
aa.manufacturer
) a
GROUP BY
a.product_group
Explanation:
This still uses a form of subquery, but one which executes only once as opposed to one that executes on a row-by-row basis such as in your original example.
It works by first selecting the product_group id, the manufacturer, and the count of how many times the manufacturer appears for each particular group.
The FROM sub-select will look something like this after execution (just making up data here):
product_group | manufacturer | occurrences
---------------------------------------------------
1 | XYZ | 4
1 | Test | 2
1 | Singleton | 1
2 | Eloran | 2
2 | XYZ | 1
Now that we have the sub-select result, we need to pick out the row that has the maximum in the occurences field for each product group.
In the outer query, we group the subselect once again by the product_group field, but this time, only the product_group field. Now when we do our GROUP BY here, we can use a really compelling function in MySQL called GROUP_CONCAT which we can use to concatenate the manufacturers together and in any order we want.
...GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'...
What we are doing here is concatenating the manufacturers together that are grouped together per product_group id, the ORDER BY a.occurrences DESC makes sure that the manufacturer with the most appearances appears first in the concatenated list. Finally we are separating each manufacturer with :::. The result of this for product_group 1 will look like:
XYZ:::Test:::Singleton
XYZ appears first since it has the highest value in the occurance field. We only want to select XYZ, so we encase the concatenation within SUBSTRING_INDEX, which will allow us to only pick the first element of the list based on the ::: delimiter.
The end result will be:
product_group | manufacturer_mode
---------------------------------------
1 | XYZ
2 | Eloran
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
I have a column called "menu_order" which has no default value. When I select the contents of this column using the following select statement:
SELECT * FROM categories ORDER BY menu_order ASC
It lists the category items that have nothing as their menu order first and then the one's that have 1's and 2's and 3's. Is there any way to prevent SQL from take nothing to come before numbers when I am trying to list things in order?
So for example, if I have:
cat_name | menu_order
----------------------
Lunch | 1
Dinner |
And I perform my query, the output should be:
Lunch Dinner
Not:
Dinner Lunch
This will put the null values last:
SELECT *
FROM categories
ORDER BY menu_order IS NULL ASC, menu_order ASC
You can use the IFNULL function in the order by with a large number
ORDER BY IFNULL(menu_order, 1000) ASC
You can even try using a case statement
ORDER BY
CASE
WHEN menu_order IS NULL THEN 1
ELSE 0
END ASC,
menu_order ASC
ORDER BY IFNULL(menu_order, 99999999) ASC