user2634794
user2634794

Reputation: 63

Converting MSSQL to MySQL

Hye, I'm trying to convert a MSSQL query over to MYSQL and it's causing me issues. This is beyond my current comfort zone. Below is my current query.

WITH n AS ( 
  SELECT n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n) /* create a numbers table with 10 rows */ 
) 
, d AS ( /* Create a table with a row for each day in the date range */ 
         /* Use cross join to increase the rows in this table and then use top() to only return the rows we need */ 
   SELECT top (datediff(day, '2017-07-04', '2018-03-02')+1) 
   SessionDate = convert(datetime,dateadd(day,row_number() over(order by (select 1))-1,'2017-07-04')) 
   FROM n AS ten 
   CROSS JOIN n AS hundred /* cross join the numbers table to create 100 rows */ 
   CROSS JOIN n AS thousand /* cross join the numbers table to create 1,000 rows */ 
   CROSS JOIN n AS tenK /* cross join the numbers table to create 10,000 rows */ 
   CROSS JOIN n AS hundredK /* cross join the numbers table to create 100,000 rows */ 
   ORDER BY SessionDate 
) 
, h as ( /* add time ranges to date table */ 
    SELECT SessionDate, StartDateTime = dateadd(hour,v.s,SessionDate), EndDateTime = dateadd(hour,v.e,SessionDate), v.point 
    FROM d 
    CROSS APPLY (values 
       (0,12,'morning') 
       ,(12,17,'afternoon') 
       ,(17,24,'evening') 
    ) 
    v (s,e,point) 
) 
SELECT *
FROM h

It's using a numbers table and splitting out the dates into different time frames. Below is an example of the result set

SessionDate             | StartDateTime           | EndDateTime             | Point
2017-07-04 00:00:00.000 | 2017-07-04 00:00:00.000 | 2017-07-04 12:00:00.000 | morning
2017-07-04 00:00:00.000 | 2017-07-04 12:00:00.000 | 2017-07-04 17:00:00.000 | afternoon
2017-07-04 00:00:00.000 | 2017-07-04 17:00:00.000 | 2017-07-05 00:00:00.000 | evening
2017-07-05 00:00:00.000 | 2017-07-05 00:00:00.000 | 2017-07-05 12:00:00.000 | morning
2017-07-05 00:00:00.000 | 2017-07-05 12:00:00.000 | 2017-07-05 17:00:00.000 | afternoon
2017-07-05 00:00:00.000 | 2017-07-05 17:00:00.000 | 2017-07-06 00:00:00.000 | evening
2017-07-06 00:00:00.000 | 2017-07-06 00:00:00.000 | 2017-07-06 12:00:00.000 | morning
2017-07-06 00:00:00.000 | 2017-07-06 12:00:00.000 | 2017-07-06 17:00:00.000 | afternoon
2017-07-06 00:00:00.000 | 2017-07-06 17:00:00.000 | 2017-07-07 00:00:00.000 | evening

Upvotes: 0

Views: 87

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131364

The query is too clever - it uses a CTE to generate a sequence of numbers instead of a calendar table, it uses CROSS APPLY to generate hours instead of using a lookup table for hours and names. The resulting execution plan will be bad.

A very simple calendar table and a 'Sessions` table will allow you to create a far simpler T-SQL query, eg :

CREATE TABLE Calendar (Date date primary key not null)
GO
--Omit code to fill the calendar
CREATE TABLE Sessions (StartTime int,EndTime int, Name nvarchar(20))
GO
insert into Sessions (StartTime,EndTime,Name)
VALUES
(0,12,'morning'),
(12,17,'afternoon'),
(17,24,'evening') 


select Date as SessionDate,
    dateadd(hour,StartTime,Date) as StartTime,
    dateadd(hour,EndTime,Date) as EndTimeTime,
    Name
from Calendar,Sessions
where Date between @startDate and @endDate

The range query will be very fast because the Date column is indexed. The execution plan will simply return all applicable date rows and combine them with the Session rows.

This can be easily converted to MySQL's dialect, eg by using DATE_ADD instead of DATEADD

Upvotes: 2

Related Questions