@@ -56,6 +56,38 @@ export class MysqlQuery extends BaseQuery {
5656 return `CAST(${ GRANULARITY_TO_INTERVAL [ granularity ] ( dimension ) } AS DATETIME)` ;
5757 }
5858
59+ public dimensionTimeGroupedColumn ( dimension : string , interval : string , offset : string ) : string {
60+ if ( this . isGranularityNaturalAligned ( interval ) ) {
61+ return super . dimensionTimeGroupedColumn ( dimension , interval , offset ) ;
62+ }
63+
64+ // Formula:
65+ // SELECT TIMESTAMPADD(
66+ // SECOND,
67+ // FLOOR(TIMESTAMPDIFF(SECOND, DATE_ADD(DATE_FORMAT(dimension, '%Y-01-01 00:00:00'), INTERVAL offset),
68+ // dimension) /
69+ // TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', '1970-01-01 00:00:00' + INTERVAL interval))
70+ // * TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', '1970-01-01 00:00:00' + INTERVAL interval),
71+ // DATE_ADD(DATE_FORMAT(dimension, '%Y-01-01 00:00:00'), INTERVAL offset)
72+ // )
73+ //
74+ // The formula operates with seconds so it won't produce dates aligned with offset date parts, like:
75+ // if offset is "6 months 3 days" - the result won't always be the 3rd of July. It will add
76+ // exact number of seconds in the "6 months 3 days" without aligning with natural calendar.
77+
78+ let dtDate = this . timeGroupedColumn ( 'year' , dimension ) ;
79+ if ( offset ) {
80+ dtDate = this . addInterval ( dtDate , offset ) ;
81+ }
82+
83+ return `TIMESTAMPADD(
84+ SECOND,
85+ FLOOR(TIMESTAMPDIFF(SECOND, ${ dtDate } , ${ dimension } ) /
86+ TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', '1970-01-01 00:00:00' + INTERVAL ${ interval } ))
87+ * TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', '1970-01-01 00:00:00' + INTERVAL ${ interval } ),
88+ ${ dtDate } )` ;
89+ }
90+
5991 public escapeColumnName ( name ) {
6092 return `\`${ name } \`` ;
6193 }
0 commit comments