From d5c48ee75f91147b3f33c0a7068ae371303058dc Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Fri, 1 May 2026 12:09:22 -0700 Subject: [PATCH] clean-up session property string charts and insights. --- public/intl/messages/en-US.json | 1 + .../HighCardinalityPropertyChart.tsx | 133 -------------- .../session-data/SessionPropertyChart.tsx | 136 ++++++++++++++ .../SessionStringPropertyView.tsx | 53 ------ .../sessions/SessionProperties.tsx | 4 +- .../[websiteId]/session-data/stats/route.ts | 4 +- .../charts/DistributionBarChart.tsx | 172 ++++++++++++++++++ src/components/hooks/index.ts | 2 +- ...ts => useSessionDataActivityStatsQuery.ts} | 4 +- src/components/messages.ts | 1 + src/lib/types.ts | 7 - src/queries/sql/index.ts | 2 +- ...tats.ts => getSessionDataActivityStats.ts} | 12 +- .../sql/sessions/getSessionDataPivot.ts | 94 +++++----- .../sql/sessions/getSessionDataValues.ts | 16 +- 15 files changed, 381 insertions(+), 260 deletions(-) delete mode 100644 src/app/(main)/websites/[websiteId]/session-data/HighCardinalityPropertyChart.tsx create mode 100644 src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx delete mode 100644 src/app/(main)/websites/[websiteId]/session-data/SessionStringPropertyView.tsx create mode 100644 src/components/charts/DistributionBarChart.tsx rename src/components/hooks/queries/{useSessionDataStatsQuery.ts => useSessionDataActivityStatsQuery.ts} (91%) rename src/queries/sql/sessions/{getSessionDataStats.ts => getSessionDataActivityStats.ts} (92%) diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json index 38a7460d3..6614c6500 100644 --- a/public/intl/messages/en-US.json +++ b/public/intl/messages/en-US.json @@ -126,6 +126,7 @@ "filter-raw": "Raw", "filters": "Filters", "property-filter": "Property Filter", + "activity-by-property": "Activity by property", "first-click": "First click", "first-seen": "First seen", "funnel": "Funnel", diff --git a/src/app/(main)/websites/[websiteId]/session-data/HighCardinalityPropertyChart.tsx b/src/app/(main)/websites/[websiteId]/session-data/HighCardinalityPropertyChart.tsx deleted file mode 100644 index 1dd39d757..000000000 --- a/src/app/(main)/websites/[websiteId]/session-data/HighCardinalityPropertyChart.tsx +++ /dev/null @@ -1,133 +0,0 @@ -'use client'; -import { PieChart } from '@/components/charts/PieChart'; -import { Empty } from '@/components/common/Empty'; -import { useMessages, useMobile } from '@/components/hooks'; -import { ListTable } from '@/components/metrics/ListTable'; -import { CHART_COLORS } from '@/lib/constants'; -import { formatLongNumber, formatShortTime } from '@/lib/format'; -import type { PropertyLeaderboardRow } from '@/lib/types'; -import { Column, DataColumn, DataTable, Grid, Row, Text } from '@umami/react-zen'; -import { useMemo } from 'react'; - -export function HighCardinalityPropertyChart({ rows }: { rows: PropertyLeaderboardRow[] }) { - const { t, labels } = useMessages(); - const { isPhone } = useMobile(); - const activeTable = useMemo(() => rows.filter(row => row.activity > 0).slice(0, 10), [rows]); - const userMix = useMemo(() => { - const totalNew = rows.reduce((sum, row) => sum + row.newSessions, 0); - const totalReturning = rows.reduce((sum, row) => sum + row.returningSessions, 0); - const total = totalNew + totalReturning; - - return { - newCount: totalNew, - returningCount: totalReturning, - newRate: total ? (totalNew / total) * 100 : 0, - returningRate: total ? (totalReturning / total) * 100 : 0, - }; - }, [rows]); - const sessionTypeTable = useMemo(() => { - return [ - { - label: 'New', - count: userMix.newCount, - percent: userMix.newRate, - }, - { - label: 'Returning', - count: userMix.returningCount, - percent: userMix.returningRate, - }, - ].filter(row => row.count > 0); - }, [userMix]); - const sessionTypeChartData = useMemo(() => { - if (!sessionTypeTable.length) return null; - - return { - labels: sessionTypeTable.map(row => row.label), - datasets: [ - { - data: sessionTypeTable.map(row => row.count), - backgroundColor: [CHART_COLORS[0], CHART_COLORS[1]], - borderWidth: 0, - }, - ], - }; - }, [sessionTypeTable]); - - return ( - - - - - {activeTable.length === 0 ? ( - - ) : isPhone ? ( - - - - {row => ( - - - {row.label} - - - )} - - - - ) : ( - - - - - {row => ( - - - {row.label} - - - )} - - - {row => formatLongNumber(row.sessions)} - - - {row => formatLongNumber(row.visits)} - - - {row => formatLongNumber(row.views)} - - - {row => formatLongNumber(row.events)} - - - {row => - formatShortTime(Math.abs(~~Number(row.totaltime)), ['h', 'm', 's'], ' ') - } - - - - - )} - - - - - - - {sessionTypeChartData && } - - - - ); -} diff --git a/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx b/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx new file mode 100644 index 000000000..b175908df --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx @@ -0,0 +1,136 @@ +'use client'; +import { DistributionBarChart } from '@/components/charts/DistributionBarChart'; +import { Empty } from '@/components/common/Empty'; +import { LoadingPanel } from '@/components/common/LoadingPanel'; +import { useMessages, useMobile, useSessionDataActivityStatsQuery } from '@/components/hooks'; +import { formatLongNumber, formatShortTime } from '@/lib/format'; +import type { PropertyFilter } from '@/lib/types'; +import { Column, DataColumn, DataTable, Grid, Row, Text } from '@umami/react-zen'; +import { useMemo } from 'react'; + +export function SessionPropertyChart({ + websiteId, + propertyName, + propertyFilters = [], +}: { + websiteId: string; + propertyName: string; + propertyFilters?: PropertyFilter[]; +}) { + const statsQuery = useSessionDataActivityStatsQuery(websiteId, propertyName, propertyFilters); + const rows = statsQuery.data ?? []; + const { t, labels } = useMessages(); + const { isPhone } = useMobile(); + const activeTable = useMemo(() => rows.filter(row => row.activity > 0).slice(0, 10), [rows]); + const chartData = useMemo( + () => + activeTable.map(row => ({ + label: row.label, + values: { + sessions: row.sessions, + visits: row.visits, + views: row.views, + events: row.events, + }, + })), + [activeTable], + ); + + return ( + + + + {chartData.length ? ( + + {t(labels.activityByProperty)} + row.label)} + datasets={[ + { + label: t(labels.visitors), + values: chartData.map(row => row.values.sessions), + backgroundColor: 'rgba(59, 130, 246, 0.80)', + }, + { + label: t(labels.visits), + values: chartData.map(row => row.values.visits), + backgroundColor: 'rgba(16, 185, 129, 0.80)', + }, + { + label: t(labels.views), + values: chartData.map(row => row.values.views), + backgroundColor: 'rgba(245, 158, 11, 0.80)', + }, + { + label: t(labels.events), + values: chartData.map(row => row.values.events), + backgroundColor: 'rgba(244, 114, 182, 0.80)', + }, + ]} + stacked={true} + /> + + ) : ( + + )} + + + + + {activeTable.length === 0 ? ( + + ) : isPhone ? ( + + + + {row => ( + + + {row.label} + + + )} + + + + ) : ( + + + + + {row => ( + + + {row.label} + + + )} + + + {row => formatLongNumber(row.sessions)} + + + {row => formatLongNumber(row.visits)} + + + {row => formatLongNumber(row.views)} + + + {row => formatLongNumber(row.events)} + + + {row => + formatShortTime(Math.abs(~~Number(row.totaltime)), ['h', 'm', 's'], ' ') + } + + + + + )} + + + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/session-data/SessionStringPropertyView.tsx b/src/app/(main)/websites/[websiteId]/session-data/SessionStringPropertyView.tsx deleted file mode 100644 index e8a623220..000000000 --- a/src/app/(main)/websites/[websiteId]/session-data/SessionStringPropertyView.tsx +++ /dev/null @@ -1,53 +0,0 @@ -'use client'; -import { LoadingPanel } from '@/components/common/LoadingPanel'; -import { useSessionDataStatsQuery } from '@/components/hooks'; -import type { PropertyFilter } from '@/lib/types'; -import { PropertyChart } from '@/components/property-data/PropertyChart'; -import { HighCardinalityPropertyChart } from './HighCardinalityPropertyChart'; - -const HIGH_CARDINALITY_NAME_PATTERN = - /(email|e-mail|name|(^|_)(id|uuid|token)($|_)|distinct_id|user_id|customer_id|client_id|member_id)/i; - -function isHighCardinalityProperty(propertyName: string, totalValues: number, uniqueValues: number) { - if (!totalValues) return false; - - const uniquenessRate = uniqueValues / totalValues; - const hasHighCardinalityName = HIGH_CARDINALITY_NAME_PATTERN.test(propertyName); - - return totalValues >= 20 && (hasHighCardinalityName || uniqueValues >= 20 || uniquenessRate >= 0.6); -} - -export function SessionStringPropertyView({ - websiteId, - propertyName, - propertyFilters = [], -}: { - websiteId: string; - propertyName: string; - propertyFilters?: PropertyFilter[]; -}) { - const statsQuery = useSessionDataStatsQuery(websiteId, propertyName, propertyFilters); - const rows = statsQuery.data ?? []; - const totalValues = rows.reduce((sum, row) => sum + row.sessions, 0); - const uniqueValues = rows.length; - const isHighCardinality = isHighCardinalityProperty( - propertyName, - totalValues, - uniqueValues, - ); - - return ( - - {isHighCardinality ? ( - - ) : ( - - )} - - ); -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx index 13f7b1c60..56643d2d8 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx @@ -11,7 +11,7 @@ import { PropertyFilterButton } from '@/components/property-data/PropertyFilterB import { PropertyNumericChart } from '@/components/property-data/PropertyNumericChart'; import { Panel } from '@/components/common/Panel'; import { SessionDataPivotTable } from '../session-data/SessionDataPivotTable'; -import { SessionStringPropertyView } from '../session-data/SessionStringPropertyView'; +import { SessionPropertyChart } from '../session-data/SessionPropertyChart'; export function SessionProperties({ websiteId }: { websiteId: string }) { const [propertyName, setPropertyName] = useState(''); @@ -129,7 +129,7 @@ export function SessionProperties({ websiteId }: { websiteId: string }) { /> )} {propertyName && selectedProperty?.dataType === DATA_TYPE.string && ( - (null); + const { theme } = useTheme(); + const { colors } = useMemo(() => getThemeColors(theme), [theme]); + + const chartData = useMemo(() => { + if (datasets?.length && labels?.length) { + return { + labels, + datasets: datasets.map(dataset => ({ + label: dataset.label, + data: dataset.values, + backgroundColor: dataset.backgroundColor, + borderColor: dataset.borderColor || dataset.backgroundColor, + borderWidth: 1, + })), + }; + } + + return { + labels: (data || []).map(item => item.label), + datasets: [ + { + label: '', + data: (data || []).map(item => item.count), + backgroundColor, + borderColor, + borderWidth: 1, + }, + ], + }; + }, [data, labels, datasets, backgroundColor, borderColor]); + + const chartOptions = useMemo( + () => ({ + indexAxis: horizontal ? ('y' as const) : ('x' as const), + scales: { + x: { + type: horizontal ? ('linear' as const) : ('category' as const), + min: horizontal ? 0 : undefined, + beginAtZero: horizontal ? true : undefined, + stacked, + grid: { + display: horizontal ? true : false, + color: colors.chart.line, + }, + border: { + color: colors.chart.line, + }, + ticks: { + color: colors.chart.text, + autoSkip: horizontal ? undefined : true, + maxRotation: horizontal ? undefined : 0, + callback: horizontal + ? (tickValue: string | number) => renderNumberLabels(String(tickValue)) + : (tickValue: string | number) => chartData.labels?.[Number(tickValue)] || '', + }, + }, + y: { + type: horizontal ? ('category' as const) : ('linear' as const), + min: horizontal ? undefined : 0, + beginAtZero: horizontal ? undefined : true, + stacked, + grid: { + display: horizontal ? false : true, + color: colors.chart.line, + }, + border: { + color: colors.chart.line, + }, + ticks: { + color: colors.chart.text, + callback: horizontal + ? (tickValue: string | number) => chartData.labels?.[Number(tickValue)] || '' + : (tickValue: string | number) => renderNumberLabels(String(tickValue)), + }, + }, + }, + }), + [chartData.labels, colors, horizontal, stacked], + ); + + const handleTooltip = useCallback(({ tooltip }: { tooltip: any }) => { + const { opacity, labelColors, dataPoints } = tooltip; + const point = dataPoints?.[0]; + const nextTooltip = opacity + ? { + title: (point?.label ?? '').toString(), + color: labelColors?.[0]?.backgroundColor, + value: `${formatLongNumber( + Number(horizontal ? point?.raw?.x ?? point?.raw ?? 0 : point?.raw?.y ?? point?.raw ?? 0), + )}${point?.dataset?.label ? ` ${point.dataset.label}` : ''}`, + } + : null; + + setTooltip(prev => { + if ( + prev?.title === nextTooltip?.title && + prev?.color === nextTooltip?.color && + prev?.value === nextTooltip?.value + ) { + return prev; + } + + return nextTooltip; + }); + }, [horizontal]); + + return ( + <> + + {tooltip && } + + ); +} + +export const DistributionBarChart = memo(DistributionBarChartComponent); + +DistributionBarChart.displayName = 'DistributionBarChart'; diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts index bd508317d..a5dfd589f 100644 --- a/src/components/hooks/index.ts +++ b/src/components/hooks/index.ts @@ -47,7 +47,7 @@ export * from './queries/useSessionActivityQuery'; export * from './queries/useSessionDataPropertiesQuery'; export * from './queries/useSessionDataPivotQuery'; export * from './queries/useSessionDataQuery'; -export * from './queries/useSessionDataStatsQuery'; +export * from './queries/useSessionDataActivityStatsQuery'; export * from './queries/useSessionDataValuesQuery'; export * from './queries/useSessionReplaysQuery'; export * from './queries/useShareTokenQuery'; diff --git a/src/components/hooks/queries/useSessionDataStatsQuery.ts b/src/components/hooks/queries/useSessionDataActivityStatsQuery.ts similarity index 91% rename from src/components/hooks/queries/useSessionDataStatsQuery.ts rename to src/components/hooks/queries/useSessionDataActivityStatsQuery.ts index 8380fedf5..72ca11fd5 100644 --- a/src/components/hooks/queries/useSessionDataStatsQuery.ts +++ b/src/components/hooks/queries/useSessionDataActivityStatsQuery.ts @@ -4,7 +4,7 @@ import { useApi } from '../useApi'; import { useDateParameters } from '../useDateParameters'; import { useFilterParameters } from '../useFilterParameters'; -export function useSessionDataStatsQuery( +export function useSessionDataActivityStatsQuery( websiteId: string, propertyName: string, propertyFilters: PropertyFilter[] = [], @@ -16,7 +16,7 @@ export function useSessionDataStatsQuery( return useQuery({ queryKey: [ - 'websites:session-data:stats', + 'websites:session-data:activity-stats', { websiteId, propertyName, propertyFilters, startAt, endAt, unit, timezone, ...params }, ], queryFn: () => diff --git a/src/components/messages.ts b/src/components/messages.ts index 79adab814..72ce903cf 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -191,6 +191,7 @@ export const labels: Record = { filter: 'label.filter', filters: 'label.filters', propertyFilter: 'label.property-filter', + activityByProperty: 'label.activity-by-property', breakdown: 'label.breakdown', true: 'label.true', false: 'label.false', diff --git a/src/lib/types.ts b/src/lib/types.ts index 587f77b96..f512c50bc 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -89,11 +89,6 @@ export interface SessionDataPivotRow { propertyValues: string[]; } -export interface PropertyCardinalityBucket { - label: string; - count: number; -} - export interface PropertyLeaderboardRow { label: string; activity: number; @@ -102,8 +97,6 @@ export interface PropertyLeaderboardRow { views: number; events: number; totaltime: number; - newSessions: number; - returningSessions: number; } export interface QueryOptions { diff --git a/src/queries/sql/index.ts b/src/queries/sql/index.ts index 13800ef3e..380565471 100644 --- a/src/queries/sql/index.ts +++ b/src/queries/sql/index.ts @@ -48,7 +48,7 @@ export * from './sessions/getSessionDataPropertySeries'; export * from './sessions/getSessionDataNumericSeries'; export * from './sessions/getSessionDataNumericStats'; export * from './sessions/getSessionDataPivot'; -export * from './sessions/getSessionDataStats'; +export * from './sessions/getSessionDataActivityStats'; export * from './sessions/getSessionDataValues'; export * from './sessions/getSessionExpandedMetrics'; export * from './sessions/getSessionMetrics'; diff --git a/src/queries/sql/sessions/getSessionDataStats.ts b/src/queries/sql/sessions/getSessionDataActivityStats.ts similarity index 92% rename from src/queries/sql/sessions/getSessionDataStats.ts rename to src/queries/sql/sessions/getSessionDataActivityStats.ts index d0ea361cd..3da98140b 100644 --- a/src/queries/sql/sessions/getSessionDataStats.ts +++ b/src/queries/sql/sessions/getSessionDataActivityStats.ts @@ -4,9 +4,9 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { PropertyFilter, PropertyLeaderboardRow, QueryFilters } from '@/lib/types'; -const FUNCTION_NAME = 'getSessionDataStats'; +const FUNCTION_NAME = 'getSessionDataActivityStats'; -export async function getSessionDataStats( +export async function getSessionDataActivityStats( ...args: [websiteId: string, propertyName: string, filters: QueryFilters, propertyFilters?: PropertyFilter[]] ): Promise { return runQuery({ @@ -90,9 +90,7 @@ async function relationalQuery( coalesce(sum(session_stats.visits), 0) as visits, coalesce(sum(session_stats.views), 0) as views, coalesce(sum(session_stats.events), 0) as events, - coalesce(sum(session_stats.totaltime), 0) as totaltime, - coalesce(sum(case when session_stats.visits = 1 then 1 else 0 end), 0) as "newSessions", - coalesce(sum(case when session_stats.visits > 1 then 1 else 0 end), 0) as "returningSessions" + coalesce(sum(session_stats.totaltime), 0) as totaltime from property_values join session_stats on session_stats.session_id = property_values.session_id group by property_values.value @@ -170,9 +168,7 @@ async function clickhouseQuery( ifNull(sum(session_stats.visits), 0) as visits, ifNull(sum(session_stats.views), 0) as views, ifNull(sum(session_stats.events), 0) as events, - ifNull(sum(session_stats.totaltime), 0) as totaltime, - ifNull(sum(if(session_stats.visits = 1, 1, 0)), 0) as newSessions, - ifNull(sum(if(session_stats.visits > 1, 1, 0)), 0) as returningSessions + ifNull(sum(session_stats.totaltime), 0) as totaltime from property_values join session_stats on session_stats.session_id = property_values.session_id group by property_values.value diff --git a/src/queries/sql/sessions/getSessionDataPivot.ts b/src/queries/sql/sessions/getSessionDataPivot.ts index 5ce922008..ac4528123 100644 --- a/src/queries/sql/sessions/getSessionDataPivot.ts +++ b/src/queries/sql/sessions/getSessionDataPivot.ts @@ -55,16 +55,28 @@ async function relationalQuery( ${filterQuery} ${pfSQL} ), - selected_property_sessions as ( - select distinct session_data.session_id - from session_data - join filtered_sessions - on filtered_sessions.session_id = session_data.session_id - where session_data.website_id = {{websiteId::uuid}} - and session_data.data_key = {{propertyName}} + latest_session_properties as ( + select + ranked.session_id, + ranked.data_key + from ( + select + session_data.session_id, + session_data.data_key, + row_number() over ( + partition by session_data.session_id, session_data.data_key + order by session_data.created_at desc, session_data.session_data_id desc + ) as row_num + from session_data + join filtered_sessions + on filtered_sessions.session_id = session_data.session_id + where session_data.website_id = {{websiteId::uuid}} + ) ranked + where ranked.row_num = 1 ) select count(*) as num - from selected_property_sessions + from latest_session_properties + where latest_session_properties.data_key = {{propertyName}} `, { ...queryParams, websiteId, propertyName, ...pfParams }, )) as { num: number }[]; @@ -83,14 +95,6 @@ async function relationalQuery( ${filterQuery} ${pfSQL} ), - selected_property_sessions as ( - select distinct session_data.session_id - from session_data - join filtered_sessions - on filtered_sessions.session_id = session_data.session_id - where session_data.website_id = {{websiteId::uuid}} - and session_data.data_key = {{propertyName}} - ), latest_session_properties as ( select ranked.session_id, @@ -116,17 +120,19 @@ async function relationalQuery( order by session_data.created_at desc, session_data.session_data_id desc ) as row_num from session_data - join selected_property_sessions - on selected_property_sessions.session_id = session_data.session_id + join filtered_sessions + on filtered_sessions.session_id = session_data.session_id where session_data.website_id = {{websiteId::uuid}} ) ranked where ranked.row_num = 1 ), paged_sessions as ( - select latest_session_properties.session_id + select + latest_session_properties.session_id, + latest_session_properties.created_at as sort_created_at from latest_session_properties - group by latest_session_properties.session_id - order by max(latest_session_properties.created_at) desc + where latest_session_properties.data_key = {{propertyName}} + order by latest_session_properties.created_at desc limit ${size} offset ${offset} ) select @@ -146,9 +152,10 @@ async function relationalQuery( order by latest_session_properties.data_key asc ) as "propertyValues" from latest_session_properties - join paged_sessions on paged_sessions.session_id = latest_session_properties.session_id - group by latest_session_properties.session_id - order by max(latest_session_properties.created_at) desc + join paged_sessions + on paged_sessions.session_id = latest_session_properties.session_id + group by latest_session_properties.session_id, paged_sessions.sort_created_at + order by paged_sessions.sort_created_at desc `, { ...queryParams, websiteId, propertyName, ...pfParams }, FUNCTION_NAME, @@ -187,15 +194,21 @@ async function clickhouseQuery( ${filterQuery} ${pfSQL} ), - selected_property_sessions as ( - select distinct session_data.session_id + latest_session_properties as ( + select + session_data.session_id as session_id, + session_data.data_key as data_key from session_data final - join filtered_sessions on filtered_sessions.session_id = session_data.session_id + join filtered_sessions + on filtered_sessions.session_id = session_data.session_id where session_data.website_id = {websiteId:UUID} - and session_data.data_key = {propertyName:String} + group by + session_data.session_id, + session_data.data_key ) select count() as num - from selected_property_sessions + from latest_session_properties + where latest_session_properties.data_key = {propertyName:String} `, { ...queryParams, websiteId, propertyName, ...pfParams }, )) as { num: number }[]; @@ -212,13 +225,6 @@ async function clickhouseQuery( ${filterQuery} ${pfSQL} ), - selected_property_sessions as ( - select distinct session_data.session_id - from session_data final - join filtered_sessions on filtered_sessions.session_id = session_data.session_id - where session_data.website_id = {websiteId:UUID} - and session_data.data_key = {propertyName:String} - ), latest_session_properties as ( select session_data.session_id as session_id, @@ -230,8 +236,8 @@ async function clickhouseQuery( argMax(session_data.date_value, session_data.created_at) as date_value, max(session_data.created_at) as created_at from session_data final - join selected_property_sessions - on selected_property_sessions.session_id = session_data.session_id + join filtered_sessions + on filtered_sessions.session_id = session_data.session_id where session_data.website_id = {websiteId:UUID} group by session_data.session_id, @@ -239,10 +245,11 @@ async function clickhouseQuery( ), paged_sessions as ( select - latest_session_properties.session_id + latest_session_properties.session_id, + latest_session_properties.created_at as sort_created_at from latest_session_properties - group by latest_session_properties.session_id - order by max(latest_session_properties.created_at) desc + where latest_session_properties.data_key = {propertyName:String} + order by latest_session_properties.created_at desc limit ${size} offset ${offset} ) select @@ -262,8 +269,9 @@ async function clickhouseQuery( join paged_sessions on paged_sessions.session_id = latest_session_properties.session_id group by - latest_session_properties.session_id - order by createdAt desc + latest_session_properties.session_id, + paged_sessions.sort_created_at + order by paged_sessions.sort_created_at desc `, { ...queryParams, websiteId, propertyName, ...pfParams }, FUNCTION_NAME, diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index e015e30ef..1c7434768 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -31,7 +31,7 @@ async function relationalQuery( ` select array_item.value as "value", - count(distinct session_data.session_id) as "total" + count(*) as "total" from website_event ${cohortQuery} ${joinSessionQuery} @@ -46,7 +46,7 @@ async function relationalQuery( ${filterQuery} group by array_item.value order by 2 desc - limit 100 + limit 500 `, queryParams, FUNCTION_NAME, @@ -61,7 +61,7 @@ async function relationalQuery( when data_type = 4 then ${getDateSQL('date_value', 'hour')} else string_value end as "value", - count(distinct session_data.session_id) as "total" + count(*) as "total" from website_event ${cohortQuery} ${joinSessionQuery} @@ -75,7 +75,7 @@ async function relationalQuery( ${filterQuery} group by value order by 2 desc - limit 100 + limit 500 `, queryParams, FUNCTION_NAME, @@ -95,7 +95,7 @@ async function clickhouseQuery( ` select arrayJoin(JSONExtract(ifNull(session_data.string_value, '[]'), 'Array(String)')) as "value", - uniq(session_data.session_id) as "total" + count() as "total" from website_event ${cohortQuery} join session_data final @@ -108,7 +108,7 @@ async function clickhouseQuery( ${filterQuery} group by value order by 2 desc - limit 100 + limit 500 `, queryParams, FUNCTION_NAME, @@ -121,7 +121,7 @@ async function clickhouseQuery( multiIf(data_type = 2, replaceAll(string_value, '.0000', ''), data_type = 4, toString(date_trunc('hour', date_value)), string_value) as "value", - uniq(session_data.session_id) as "total" + count() as "total" from website_event ${cohortQuery} join session_data final @@ -134,7 +134,7 @@ async function clickhouseQuery( ${filterQuery} group by value order by 2 desc - limit 100 + limit 500 `, queryParams, FUNCTION_NAME,