Reputation: 63
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
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