Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order by day_of_week in MySQL

How can I order the mysql result by varchar column that contains day of week name?

Note that MONDAY should goes first, not SUNDAY.

like image 364
Bogdan Gusiev Avatar asked Jul 14 '09 17:07

Bogdan Gusiev


People also ask

What does ORDER BY do in MySQL?

The ORDER BY keyword is used to sort the result-set in ascending or descending order. The ORDER BY keyword sorts the records in ascending order by default. To sort the records in descending order, use the DESC keyword.

How do I ORDER BY weekday in SQL?

select ename, to_char(hiredate,'fmDay') as "Day" order by "Day"; Then it sorts the result based on Day like; from Friday, then Monday and last Wednesday, like sorting by characters.

Can we use two ORDER BY in MySQL?

This sorts your MySQL table result in Ascending or Descending order according to the specified column. The default sorting order is Ascending which you can change using ASC or DESC . SELECT * FROM [table-name] ORDER BY [column-name1 ] [ASC|DESC] , [column-name2] [ASC|DESC],..

What does ORDER BY 1 do in SQL?

it simply means sorting the view or table by 1st column of the query's result.


6 Answers

Either redesign the column as suggested by Williham Totland, or do some string parsing to get a date representation.

If the column only contains the day of week, then you could do this:

ORDER BY FIELD(<fieldname>, 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY');
like image 117
Glen Solsberry Avatar answered Oct 26 '22 01:10

Glen Solsberry


Why not this?

ORDER BY (
    CASE DAYOFWEEK(dateField)
    WHEN 1 THEN 7 ELSE DAYOFWEEK(dateField)
    END
)

I believe this orders Monday to Sunday...

like image 37
Joseph Manganelli Avatar answered Oct 26 '22 02:10

Joseph Manganelli


I'm thinking that short of redesigning the column to use an enum instead, there's not a lot to be done for it, apart from sorting the results after you've gotten them out.

Edit: A dirty hack is of course to add another table with id:weekday pairs and using joins or select in selects to fake an enum.

like image 23
Williham Totland Avatar answered Oct 26 '22 02:10

Williham Totland


This looks messy but still works and seems more generic:

select day, 
case day
  when 'monday' then 1
  when 'tuesday' then 2
  when 'wednesday' then 3
  when 'thursday' then 4
  when 'friday' then 5
  when 'saturday' then 6
  when 'sunday' then 7
end as day_nr from test order by day_nr;

Using if is even more generic and messier:

select id, day, 
if(day = 'monday',1,
  if(day = 'tuesday',2,
    if(day = 'wednesday',3,
      if(day = 'thursday',4,
        if(day = 'friday',5,
          if(day = 'saturday',6,7)
        )
      )
    )
  )
) as day_nr from test order by day_nr;

You can also hide the details of conversion from name to int in stored procedure.

like image 44
niteria Avatar answered Oct 26 '22 02:10

niteria


... ORDER BY date_format(order_date, '%w') = 0, date_format(order_date, '%w') ;

like image 42
shantanuo Avatar answered Oct 26 '22 00:10

shantanuo


I realise that this is an old thread, but as it comes to the top of google for certain search times I will use it to share my approach.

I wanted the same result as the original question, but in addition I wanted the ordering of the results starting from the current day of the week and then progressing through the rest of the days.

I created a separate table, in which the days were listed over a fortnight, so that no matter which day you started from you could run through a sequence of 7 days.

CREATE TABLE IF NOT EXISTS `Weekdays` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;

INSERT INTO `Weekdays` (`id`, `name`) VALUES
(1, 'Monday'),
(2, 'Tuesday'),
(3, 'Wednesday'),
(4, 'Thursday'),
(5, 'Friday'),
(6, 'Saturday'),
(7, 'Sunday'),
(8, 'Monday'),
(9, 'Tuesday'),
(10, 'Wednesday'),
(11, 'Thursday'),
(12, 'Friday'),
(13, 'Saturday'),
(14, 'Sunday');

I then ran the query with a variable that determined the start point in sequence and used a join to get the order number for the days. For example to start the listing at Wednesday, I do the following:

SELECT @startnum := MIN(id) FROM Weekdays WHERE name='Wednesday';
SELECT * FROM Events INNER JOIN ( SELECT id as weekdaynum, name as dayname FROM Weekdays WHERE id>(@startnum-1) AND id<(@startnum+7) ) AS s2 ON s2.dayname=Events.day ORDER BY weekdaynum;

I hope this helps someone who stumbles onto this post.

like image 39
John Hawkins Avatar answered Oct 26 '22 02:10

John Hawkins