@@ -1464,18 +1464,59 @@ export class BaseQuery {
14641464
14651465 overTimeSeriesQuery ( baseQueryFn , cumulativeMeasure , fromRollup ) {
14661466 const dateJoinCondition = cumulativeMeasure . dateJoinCondition ( ) ;
1467+ const uniqDateJoinCondition = R . uniqBy ( djc => djc [ 0 ] . dimension , dateJoinCondition ) ;
14671468 const cumulativeMeasures = [ cumulativeMeasure ] ;
14681469 if ( ! this . timeDimensions . find ( d => d . granularity ) ) {
1469- const filters = this . segments . concat ( this . filters ) . concat ( this . dateFromStartToEndConditionSql ( dateJoinCondition , fromRollup , false ) ) ;
1470+ const filters = this . segments
1471+ . concat ( this . filters )
1472+ . concat ( this . dateFromStartToEndConditionSql (
1473+ // If the same time dimension is passed more than once, no need to build the same
1474+ // filter condition again and again. Different granularities don't play role here,
1475+ // as rollingWindow.granularity is used for filtering.
1476+ uniqDateJoinCondition ,
1477+ fromRollup ,
1478+ false
1479+ ) ) ;
14701480 return baseQueryFn ( cumulativeMeasures , filters , false ) ;
14711481 }
1472- const dateSeriesSql = this . timeDimensions . map ( d => this . dateSeriesSql ( d ) ) . join ( ', ' ) ;
1473- const filters = this . segments . concat ( this . filters ) . concat ( this . dateFromStartToEndConditionSql ( dateJoinCondition , fromRollup , true ) ) ;
1482+
1483+ // We can't do meaningful query if few time dimensions with different ranges passed,
1484+ // it won't be possible to join them together without loosing some rows.
1485+ const rangedTimeDimensions = this . timeDimensions . filter ( d => d . dateRange && d . granularity ) ;
1486+ const uniqTimeDimensionWithRanges = R . uniqBy ( d => d . dateRange , rangedTimeDimensions ) ;
1487+ if ( uniqTimeDimensionWithRanges . length > 1 ) {
1488+ throw new Error ( 'Can\'t build query for time dimensions with different date ranges' ) ;
1489+ }
1490+
1491+ // We need to generate time series table for the lowest granularity among all time dimensions
1492+ let dateSeriesDimension ;
1493+ const dateSeriesGranularity = this . timeDimensions . filter ( d => d . granularity )
1494+ . reduce ( ( acc , d ) => {
1495+ const mg = this . minGranularity ( acc , d . resolvedGranularity ( ) ) ;
1496+ if ( mg === d . resolvedGranularity ( ) ) {
1497+ dateSeriesDimension = d ;
1498+ }
1499+ return mg ;
1500+ } , undefined ) ;
1501+
1502+ const dateSeriesSql = this . dateSeriesSql ( dateSeriesDimension ) ;
1503+
1504+ // If the same time dimension is passed more than once, no need to build the same
1505+ // filter condition again and again. Different granularities don't play role here,
1506+ // as rollingWindow.granularity is used for filtering.
1507+ const filters = this . segments
1508+ . concat ( this . filters )
1509+ . concat ( this . dateFromStartToEndConditionSql (
1510+ uniqDateJoinCondition ,
1511+ fromRollup ,
1512+ true
1513+ ) ) ;
14741514 const baseQuery = this . groupedUngroupedSelect (
14751515 ( ) => baseQueryFn ( cumulativeMeasures , filters ) ,
14761516 cumulativeMeasure . shouldUngroupForCumulative ( ) ,
14771517 ! cumulativeMeasure . shouldUngroupForCumulative ( ) && this . minGranularity (
1478- cumulativeMeasure . windowGranularity ( ) , this . timeDimensions . find ( d => d . granularity ) . resolvedGranularity ( )
1518+ cumulativeMeasure . windowGranularity ( ) ,
1519+ dateSeriesGranularity
14791520 ) || undefined
14801521 ) ;
14811522 const baseQueryAlias = this . cubeAlias ( 'base' ) ;
@@ -1495,28 +1536,27 @@ export class BaseQuery {
14951536 dateSeriesSql ,
14961537 baseQuery ,
14971538 dateJoinConditionSql ,
1498- baseQueryAlias
1539+ baseQueryAlias ,
1540+ dateSeriesDimension . granularity ,
14991541 ) ;
15001542 }
15011543
1502- overTimeSeriesSelect ( cumulativeMeasures , dateSeriesSql , baseQuery , dateJoinConditionSql , baseQueryAlias ) {
1503- const forSelect = this . overTimeSeriesForSelect ( cumulativeMeasures ) ;
1544+ overTimeSeriesSelect ( cumulativeMeasures , dateSeriesSql , baseQuery , dateJoinConditionSql , baseQueryAlias , dateSeriesGranularity ) {
1545+ const forSelect = this . overTimeSeriesForSelect ( cumulativeMeasures , dateSeriesGranularity ) ;
15041546 return `SELECT ${ forSelect } FROM ${ dateSeriesSql } ` +
15051547 ` LEFT JOIN (${ baseQuery } ) ${ this . asSyntaxJoin } ${ baseQueryAlias } ON ${ dateJoinConditionSql } ` +
15061548 this . groupByClause ( ) ;
15071549 }
15081550
1509- overTimeSeriesForSelect ( cumulativeMeasures ) {
1510- return this . dimensions . map ( s => s . cumulativeSelectColumns ( ) ) . concat ( this . dateSeriesSelect ( ) ) . concat (
1511- cumulativeMeasures . map ( s => s . cumulativeSelectColumns ( ) ) ,
1512- ) . filter ( c => ! ! c )
1551+ overTimeSeriesForSelect ( cumulativeMeasures , dateSeriesGranularity ) {
1552+ return this . dimensions
1553+ . map ( s => s . cumulativeSelectColumns ( ) )
1554+ . concat ( this . timeDimensions . map ( d => d . dateSeriesSelectColumn ( null , dateSeriesGranularity ) ) )
1555+ . concat ( cumulativeMeasures . map ( s => s . cumulativeSelectColumns ( ) ) )
1556+ . filter ( c => ! ! c )
15131557 . join ( ', ' ) ;
15141558 }
15151559
1516- dateSeriesSelect ( ) {
1517- return this . timeDimensions . map ( d => d . dateSeriesSelectColumn ( ) ) ;
1518- }
1519-
15201560 dateFromStartToEndConditionSql ( dateJoinCondition , fromRollup , isFromStartToEnd ) {
15211561 return dateJoinCondition . map (
15221562 // TODO these weird conversions to be strict typed for big query.
0 commit comments