How to keep mysql names together in ordered list - mysql

I have the following list of items
Category
OrderNum
Prerequisites
2
NULL
4
Prerequisites
6
Sign Off
8
Sign Off
10
I would like it to be ordered so that 'Prerequisites' is together and the NULL category appears after it, so that:
Category
OrderNum
Prerequisites
2
Prerequisites
6
NULL
4
Sign Off
8
Sign Off
10
Currently my SQL has the following order by:
ORDER BY OrderNum <> '' DESC, OrderNum
I've tried the following, however it puts NULL at the end.
ORDER BY COALESCE(Category,'') <> '' DESC, OrderNum <> '' DESC, OrderNum
I'm trying to achieve it so that the records with the same category are together in the recordset, the NULL item should appear before the 'Sign Off' category because the OrderNum of NULL is less than any of the 'Sign Off' records.
I'm not sure if that's possible in one query. Any help would be appreciated.
Thanks!

You can apply all the conditions that you want with a CASE expression:
SELECT * FROM tablename
ORDER BY CASE
WHEN Category = 'Prerequisites' THEN 1
WHEN Category IS NULL THEN 2
ELSE 3
END,
Category,
OrderNum;
or, if there are also empty strings in Category which you want sorted with the NULLs:
SELECT * FROM tablename
ORDER BY CASE
WHEN Category = 'Prerequisites' THEN 1
WHEN COALESCE(Category, '') = '' THEN 2
ELSE 3
END,
Category,
OrderNum;
or:
SELECT * FROM tablename
ORDER BY Category = 'Prerequisites' DESC,
Category IS NULL DESC, -- or: COALESCE(Category, '') = '' DESC,
Category,
OrderNum;
But, if what you want is to sort the rows by the minimum OrderNum of each Category use a correlated subquery:
SELECT t1.* FROM tablename t1
ORDER BY (SELECT MIN(t2.OrderNum) FROM tablename t2 WHERE t2.Category = t1.Category),
t1.OrderNum;
or, for MySql 8.0+ use MIN() window function:
SELECT * FROM tablename
ORDER BY MIN(OrderNum) OVER (PARTITION BY Category),
OrderNum;
See the demo.

If you want the NULL values right after Prerequisites, you can use PrerequisitesZ as the fallback for NULL values:
ORDER BY COALESCE(Category, 'PrerequisitesZ') DESC, OrderNum;

You can try using two conditions in the ORDER BY clause:
if Category has the value "Prerequisites", it should come first
otherwise order by the OrderNum value
Here's how you would do it:
SELECT *
FROM tab
ORDER BY IF(Category='Prerequisites', 0, 1),
OrderNum
Demo here.
Note: Actually you can play how much you want with the conditions in the ORDER BY clause, as it can accept most of MySQL constructs.

Related

select rows mysql order by custom value From the bottom of the table to the top of the table

I want Last eight posts if productgroup='برنامه نویسی' And the results that they have subject="css" Have a higher priority
this is my code :
$query = "SELECT productcode FROM (SELECT * FROM product ORDER BY productcode DESC) secondTab
WHERE productgroup='برنامه نویسی' ORDER BY FIELD(subject,'css') DESC limit 8";
But get result From the top of the table to the bottom of the table:
6
7
8
10
14
20
34
2
The ORDER BY clause inside the subquery is useless.
Sort the results like this:
SELECT productcode
FROM product
WHERE productgroup = 'برنامه نویسی'
ORDER BY FIELD(subject,'css') DESC, productcode DESC
LIMIT 8
If you want product code 21 to be last, use two order by keys:
order by (productcode = 21) asc, -- put it last
productcode desc
MySQL treats boolean values as integers in a numeric context, with 0 for false and 1 for true. Hence, "false" is ordered (using ASC) before true values.

Group by - do not Group NULL and control record displayed

Similar to this question: group by not-null values
I'm trying to only group my records that have the column groupID not null:
+--+-------+------+-----+-----+----------+
|id|groupId|isMain|name |stars|created |
+--+-------+------+-----+-----+----------+
..1..abcd....1.....john....5...2018-06-01.
..2..NULL....0.....albert..3...2018-05-01.
..3..abcd....0.....clara...1...2018-06-01.
..4..NULL....0.....steph...2...2018-07-01.
With this query I'm able to group only those records where groupId is not null:
SELECT *, SUM(stars) as stars
FROM table AS
GROUP BY (case when `groupId` is null then id else `group` end)
ORDER BY created DESC
This gives me the result:
4..NULL....0.....steph...2...2018-07-01
3..NULL....0.....clara...6...2018-06-01
2..NULL....0.....albert..3...2018-05-01
I'm trying to select, for those records grouped, the ones that isMain is 1 but I have no clue how to achieve that.
I've tried playing with HAVING but that gives me a totally different result.
You could use CASE or IFNULL
but you should use proper aggregation function and group by columns clause eg:
select ifnull(groupID, id), name, sum(stars), max(created) as my_create
from table
group by ifnull(groupID, id), name
order by my_create

GROUP BY and ORDER BY in UNION

I have this query:
SELECT category, description, price, date_added, datetime_created
FROM vc_expense
WHERE trip_id=? AND description LIKE ?
GROUP BY description, price
UNION SELECT category, description, NULL, NULL, NULL
FROM vc_expense_default
WHERE description LIKE ?
ORDER BY CASE
WHEN description LIKE ? AND price THEN 1
WHEN price THEN 2
ELSE 3
END, date_added DESC, datetime_created DESC
LIMIT 5
My problem is that when I GROUP the description+price on row #4, it doesn't take into account that I want the most recent results:
date_added DESC, datetime_created DESC
Is there a way to use ORDER BY after row #4 so I can get the newest items only, it doesn't seem to work because of the UNION
Thanks!
Edit:
The UNION was irrelevant, I just had put it inside parantheses, and get the latest items only from each group, like this:
SELECT e1.category, e1.description, e1.price, e1.date_added, e1.datetime_created
FROM vc_expense e1
LEFT JOIN vc_expense e2 ON (
e1.description=e2.description AND
e1.price=e2.price AND
e1.date_added < e2.date_added
)
WHERE e2.id IS NULL AND e1.trip_id = ? AND e1.description LIKE ?
From the docs:
https://dev.mysql.com/doc/refman/5.7/en/union.html
Use of ORDER BY for individual SELECT statements implies nothing about
the order in which the rows appear in the final result because UNION
by default produces an unordered set of rows
and here's what you need:
To apply ORDER BY or LIMIT to an individual SELECT, place the clause
inside the parentheses that enclose the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

can we do in mysql a select query that order by date and add anything that expire current date on the bottom of the query?

I have a simple table example:
table name SHOW with 3 column ( id, title, representationDate).
I want to select all show and place it in order of date with distinct title because I can have the same title but at different representationDate. I want also that when I do my select query that any expire show be in the bottom of my list and all none expire show at the top by order of representationDate.
Right now I try this but don't give me the result I want.
SELECT distinct title as title
FROM SHOW
WHERE id = 23
AND representationDate > NOW()
UNION
(SELECT distinct title as title
FROM SHOW
WHERE id = 23
AND representationDate < NOW()
ORDER BY representationDate ASC)
The problem you obviously have encountered it that with unions you can order any particular parenthesized SELECT statement, but when performing the UNION across the results of the individual SELECT's, order is not guaranteed, so you could have interleaved results. You can order the overall UNIONed result set (outside of parenthesis at the end), but this will not get you what you are looking for as this would not allow you to differentiate expired records from non-expired records.
What you might want to do is to generate a calculated field by which you can sort:
SELECT
distinct title,
(CASE when representationDate >= NOW() THEN 1 ELSE 0 END CASE) as `current`
FROM SHOW
WHERE id = 23
ORDER BY `current` DESC, representationDate ASC

How to output items in Order in MySQL?

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