diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index 4b910f00..2abf230c 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -23,15 +23,15 @@ const POSTGRESQL_DATE_FORMATS = { year: 'YYYY-01-01', }; -function getAddMinutesQuery(field: string, minutes: number): string { +function getAddIntervalQuery(field: string, interval: string): string { const db = getDatabaseType(process.env.DATABASE_URL); if (db === POSTGRESQL) { - return `${field} + interval '${minutes} minute'`; + return `${field} + interval '${interval}'`; } if (db === MYSQL) { - return `DATE_ADD(${field}, interval ${minutes} minute)`; + return `DATE_ADD(${field}, interval ${interval})`; } } @@ -80,15 +80,15 @@ function getDateQuery(field: string, unit: string, timezone?: string): string { } } -function getTimestampIntervalQuery(field: string): string { +function getTimestampDiffQuery(field1: string, field2: string): string { const db = getDatabaseType(); if (db === POSTGRESQL) { - return `floor(extract(epoch from max(${field}) - min(${field})))`; + return `floor(extract(epoch from (${field2} - ${field1})))`; } if (db === MYSQL) { - return `floor(unix_timestamp(max(${field})) - unix_timestamp(min(${field})))`; + return `timestampdiff(second, ${field1}, ${field2})`; } } @@ -216,11 +216,11 @@ function getSearchMode(): { mode?: Prisma.QueryMode } { export default { ...prisma, - getAddMinutesQuery, + getAddIntervalQuery, getDayDiffQuery, getCastColumnQuery, getDateQuery, - getTimestampIntervalQuery, + getTimestampDiffQuery, getFilterQuery, parseFilters, getPageFilters, diff --git a/src/queries/analytics/getWebsiteStats.ts b/src/queries/analytics/getWebsiteStats.ts index 654a09a9..4dbdb462 100644 --- a/src/queries/analytics/getWebsiteStats.ts +++ b/src/queries/analytics/getWebsiteStats.ts @@ -12,7 +12,8 @@ export async function getWebsiteStats(...args: [websiteId: string, filters: Quer } async function relationalQuery(websiteId: string, filters: QueryFilters) { - const { getDateQuery, getTimestampIntervalQuery, parseFilters, rawQuery } = prisma; + const { getDateQuery, getAddIntervalQuery, getTimestampDiffQuery, parseFilters, rawQuery } = + prisma; const { filterQuery, joinSession, params } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, @@ -24,13 +25,16 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { sum(t.c) as "pageviews", count(distinct t.session_id) as "uniques", sum(case when t.c = 1 then 1 else 0 end) as "bounces", - sum(t.time) as "totaltime" + sum(case when t.max_time < ${getAddIntervalQuery('t.min_time', '1 hour')} + then ${getTimestampDiffQuery('t.min_time', 't.max_time')} + else 0 end) as "totaltime" from ( select website_event.session_id, - ${getDateQuery('website_event.created_at', 'hour')}, - count(*) as c, - ${getTimestampIntervalQuery('website_event.created_at')} as "time" + ${getDateQuery('website_event.created_at', 'day')}, + count(*) as "c", + min(website_event.created_at) as "min_time", + max(website_event.created_at) as "max_time" from website_event join website on website_event.website_id = website.website_id diff --git a/src/queries/analytics/reports/getFunnel.ts b/src/queries/analytics/reports/getFunnel.ts index 8dbd8d45..4387cf09 100644 --- a/src/queries/analytics/reports/getFunnel.ts +++ b/src/queries/analytics/reports/getFunnel.ts @@ -35,7 +35,7 @@ async function relationalQuery( }[] > { const { windowMinutes, startDate, endDate, urls } = criteria; - const { rawQuery, getAddMinutesQuery } = prisma; + const { rawQuery, getAddIntervalQuery } = prisma; const { levelQuery, sumQuery } = getFunnelQuery(urls, windowMinutes); function getFunnelQuery( @@ -58,9 +58,9 @@ async function relationalQuery( join website_event we on l.session_id = we.session_id where we.website_id = {{websiteId::uuid}} - and we.created_at between l.created_at and ${getAddMinutesQuery( + and we.created_at between l.created_at and ${getAddIntervalQuery( `l.created_at `, - windowMinutes, + `${windowMinutes} minute`, )} and we.referrer_path = {{${i - 1}}} and we.url_path = {{${i}}}