All Products
Search
Document Center

Hologres:finder_group_funnel

Last Updated:Mar 26, 2026

Standard funnel analysis treats all users as a single group. When you need to compare conversion rates across user segments — such as by province, acquisition channel, or device type — use finder_group_funnel to split funnel results by a TEXT dimension field.

Each user is assigned to exactly one group based on the dimension value present at the grouping event. Users who do not reach the grouping event, or whose dimension value does not match any group, are assigned to the built-in unreach group.

The function returns a BINARY-encoded result per user per group. To extract usable data, decode the output using two companion functions:

  • finder_group_funnel_res — decodes each user's per-step funnel progress

  • finder_group_funnel_text_group — decodes the group label (dimension value or unreach)

To aggregate per-user results into group-level conversion counts, pass the decoded output to funnel_rep.

Prerequisites

Before you begin, ensure that you have:

  • Hologres V2.2.32 or later

  • Superuser access to the target database

Install the extension

Run the following statement as a superuser to install the flow_analysis extension:

CREATE extension flow_analysis; -- Install the extension.

The extension is installed at the database level. Install it only once per database.

By default, the extension loads into the public schema and cannot be loaded into other schemas. To call functions from a different schema, use the public.function_name format — for example, public.windowFunnel.

How it works

finder_group_funnel processes events in three stages:

  1. Slot assignment — For each event row, server_timestamp determines which step slot (day, hour, or other interval) the event belongs to.

  2. Sorting — Within each slot, events are sorted by client_timestamp to establish the sequence.

  3. Grouping and tracking — Starting at group_event_index, users are assigned to a group based on their group_dimension value. The function then tracks each user's progress through the ordered check_event list within the window duration.

The result is a BINARY-encoded value per user per group. Pipe the output through finder_group_funnel_res and finder_group_funnel_text_group to read funnel progress and group labels.

finder_group_funnel

Groups events by the specified dimension and calculates per-user funnel results.

Syntax

finder_group_funnel(
  window,
  start_timestamp,
  step_interval,
  step_numbers,
  num_events,
  attr_related,
  group_event_index,
  time_zone,
  is_relative_window,
  server_timestamp,
  client_timestamp,
  group_dimension,
  [prop1, prop2, ...],
  check_event1, check_event2, ...
)

Parameters

ParameterRequiredTypeDescription
windowYesSize of the analysis window. Unit: milliseconds.
start_timestampYesTIMESTAMP / TIMESTAMPTZStart time of the analysis.
step_intervalYesDuration of one step (the granularity of conversion analysis). Unit: seconds. For example, 86400 = one day.
step_numbersYesNumber of steps to analyze. For example, step_interval=86400 and step_numbers=7 means the function analyzes daily funnel data for 7 days starting from start_timestamp.
num_eventsYesTotal number of events to track in the funnel.
attr_relatedYesUINT8Indicates which events have associated properties. In binary form, if the ith bit is 1, the (i+1)th event has associated properties. The number of prop expressions must equal the number of 1-bits. Set to 0 if no event has associated properties.
group_event_indexYesThe event at which grouping begins. If set to 1, users are grouped as soon as they complete the first event. If set to 2, grouping starts at the second event — users who do not reach the second event are assigned to the unreach group.
time_zoneYesTEXTTime zone of the input timestamps, in standard format (for example, Asia/Shanghai). This parameter only affects output when is_relative_window is true.
is_relative_windowYesBOOLEANWhether to use calendar-day boundaries instead of a fixed duration window. Default: false. When set to true: window must be an integer multiple of 86,400,000, and step_interval must be 86400. See the Calendar-day window section below for details.
server_timestampYesTIMESTAMP / TIMESTAMPTZServer-side event time. Used to determine which step slot each event belongs to.
client_timestampYesTIMESTAMP / TIMESTAMPTZClient-side event time. Must match the data type of start_timestamp. Used to sort events.
group_dimensionYesTEXTThe field to group by. Only TEXT fields are supported. To group by multiple fields, combine them with concat_ws or concat.
propNoAssociated properties for events with attr_related bits set to 1. All prop expressions must have the same data type.
check_eventYesOrdered list of conversion events. Events that match within the window duration count as valid conversions. Example: event = 'E0001', event = 'E0002', event = 'E0003'.

Calendar-day window

When is_relative_window=true, the window uses calendar-day boundaries rather than a fixed elapsed duration:

  • A calendar day runs from 00:00:00 to 23:59:59.

  • The first day spans from the event time to 23:59:59 on the same day.

  • Each subsequent day is a full calendar day.

Use calendar-day windows when funnel reporting periods must align to business days (midnight to midnight) rather than rolling 24-hour intervals from the first event.

Return value

An encoded result of type BINARY. Decode it with finder_group_funnel_res and finder_group_funnel_text_group.

Example

The following example groups funnel results by province over a 3-day window. User 1111 is from Beijing and user 2222 is from Zhejiang.

Step 1: Create the test table and insert data.

CREATE TABLE finder_group_funnel_test(
  id INT,
  event_time TIMESTAMP,
  event TEXT,
  province TEXT,
  city TEXT
);

INSERT INTO finder_group_funnel_test VALUES
(1111, '2024-01-02 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:01', 'logon',        'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:02', 'payment',      'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:03', 'exit',         'Beijing',  'Beijing'),

(1111, '2024-01-03 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-03 00:00:01', 'logon',        'Beijing',  'Beijing'),
(1111, '2024-01-03 00:00:02', 'payment',      'Beijing',  'Beijing'),

(1111, '2024-01-04 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-04 00:00:01', 'logon',        'Beijing',  'Beijing'),

(2222, '2024-01-02 00:00:00', 'registration', 'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:00', 'logon',        'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:01', 'payment',      'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:03', 'payment',      'Zhejiang', 'Hangzhou');

Step 2: Group results by province over a 3-day window.

SELECT
    id,
    UNNEST(
        finder_group_funnel(
            86400000 * 3,                                              -- 3-day window
            EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
            86400,                                                     -- step_interval: 1 day
            3,                                                         -- step_numbers: 3 days
            4,                                                         -- num_events: 4 events
            0,                                                         -- attr_related: no associated properties
            1,                                                         -- group_event_index: group on first event
            'Asia/Shanghai',
            FALSE,
            event_time,
            event_time,
            province,                                                  -- group_dimension
            event = 'registration',
            event = 'logon',
            event = 'payment',
            event = 'exit'
        )
    ) AS result
FROM finder_group_funnel_test
GROUP BY id;

The result is BINARY-encoded. Each row shows the user ID and their group label (province value or unreach):

  id  | result
------+---------
 2222 | Zhejiang
 2222 | unreach
 1111 | Beijing
 1111 | unreach
(4 rows)

To decode the detailed funnel progress for each group, use finder_group_funnel_res.

finder_group_funnel_res

Decodes the BINARY result from finder_group_funnel into per-user funnel details for each step.

Syntax

finder_group_funnel_res(finder_group_funnel(...))

Parameters

ParameterDescription
finder_group_funnel()The BINARY result from finder_group_funnel.

Return value

An integer array showing the furthest event reached in the overall window and in each step interval.

Example

Using the table from the finder_group_funnel example, decode each user's per-day funnel progress:

SELECT
    id,
    finder_group_funnel_res(result) AS res
FROM (
    SELECT
        id,
        UNNEST(
            finder_group_funnel(
                86400000 * 3,
                EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
                86400, 3, 4, 0, 1, 'Asia/Shanghai', FALSE,
                event_time, event_time,
                province,
                event = 'register',
                event = 'logon',
                event = 'pay',
                event = 'exit'
            )
        ) AS result
    FROM finder_group_funnel_test
    GROUP BY id
) a;

Result:

  id  |    res
------+-----------
 1111 | {4,4,3,2}
 1111 | {0,0,0,0}
 2222 | {3,3,0,0}
 2222 | {0,0,0,0}

Reading the result array: Each array has 1 + step_numbers elements. The first element is the furthest event reached across the entire window; the remaining elements are the furthest event reached within each step interval (day, in this case).

For user 1111 with result {4,4,3,2}:

PositionValueMeaning
Overall (3-day window)4Reached the 4th event (exit) within 3 days
Day 14Reached exit on day 1
Day 23Reached the 3rd event (payment) on day 2
Day 32Reached the 2nd event (logon) on day 3

finder_group_funnel_text_group

Decodes the group label (dimension value or unreach) from the BINARY result. Use it alongside finder_group_funnel_res to get both the group name and the funnel data in one query.

Syntax

finder_group_funnel_text_group(finder_group_funnel(...))

Parameters

ParameterDescription
finder_group_funnel()The BINARY result from finder_group_funnel.

Return value

The decoded group label as text — the dimension value (for example, Beijing) or unreach.

Example

The following query decodes both the group label and per-day funnel progress in a single pass:

SELECT
    id,
    finder_group_funnel_text_group(result) AS key,
    finder_group_funnel_res(result) AS res
FROM (
    SELECT
        id,
        UNNEST(
            finder_group_funnel(
                86400000 * 3,
                EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
                86400, 3, 4, 0, 1, 'Asia/Shanghai', FALSE,
                event_time, event_time,
                province,
                event = 'registration',
                event = 'logon',
                event = 'payment',
                event = 'exit'
            )
        ) AS result
    FROM finder_group_funnel_test
    GROUP BY id
) a;

Result:

  id  |   key    |    res
------+----------+-----------
 2222 | Zhejiang | {3,3,0,0}
 2222 | unreach  | {0,0,0,0}
 1111 | Beijing  | {4,4,3,2}
 1111 | unreach  | {0,0,0,0}
(4 rows)

funnel_rep

Aggregates per-user funnel results (from finder_group_funnel_res) into group-level conversion counts at each funnel step.

Syntax

funnel_rep(step_number, num_events, funnel_res)

Parameters

ParameterRequiredTypeDescription
step_numberYesUINTNumber of time slots. Typically the same as step_numbers in finder_group_funnel.
num_eventsYesUINTTotal events in the funnel. Typically the same as the number of check_event expressions.
funnel_resYesPer-user conversion step details generated by each user, which is the output of finder_group_funnel or FINDER_FUNNEL.

Return value

A string array in the format {"overall","step1","step2",...}. Each element is a comma-separated list of user counts that reached events 1 through N:

  • The first element is the overall count across the full window.

  • Each subsequent element is the count within that step interval.

Example

Using the data from the finder_group_funnel example, calculate how many users reached each event across a 3-day window with a 1-day step:

-- 3-day window, 1-day step: count users reaching each event per day.
SELECT
    funnel_rep(3, 4, funnel_res)
FROM (
    SELECT
        id,
        FINDER_FUNNEL(
            86400000 * 3,
            EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
            86400, 3, 4, 0, 'Asia/Shanghai', FALSE,
            event_time, event_time,
            event = 'registration',
            event = 'logon',
            event = 'payment',
            event = 'exit'
        ) AS funnel_res
    FROM finder_group_funnel_test
    GROUP BY id
) a;

Result:

                funnel_rep
-------------------------------------------
 {"2,2,2,1","2,2,2,1","1,1,1,0","1,1,0,0"}
(1 row)

Reading this result with step_numbers=3 and num_events=4:

ElementValueMeaning
Overall2,2,2,1Across 3 days: 2 users reached event 1, 2 reached event 2, 2 reached event 3, 1 reached event 4
Day 12,2,2,1On day 1: same pattern
Day 21,1,1,0On day 2: 1 user reached events 1–3, none reached event 4
Day 31,1,0,0On day 3: 1 user reached events 1–2, none reached events 3–4

Complete examples

Scenario 1: Group funnel results by dimension over a multi-day window

Goal: An e-commerce team wants to compare how users from Beijing, Shanghai, and Zhejiang convert through a 4-step flow (registration → logon → payment → exit) within a 3-day rolling window, with daily breakdowns. The team expects Beijing users to show the highest completion rate across all days.

Step 1: Create the test table and insert data.

CREATE TABLE finder_group_funnel_test_1(
  id INT,
  event_time TIMESTAMP,
  event TEXT,
  province TEXT,
  city TEXT
);

INSERT INTO finder_group_funnel_test_1 VALUES
(1111, '2024-01-02 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:01', 'logon',        'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:02', 'payment',      'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:03', 'exit',         'Beijing',  'Beijing'),

(1111, '2024-01-03 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-03 00:00:01', 'logon',        'Beijing',  'Beijing'),
(1111, '2024-01-03 00:00:02', 'payment',      'Beijing',  'Beijing'),

(1111, '2024-01-04 00:00:00', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-04 00:00:01', 'logon',        'Beijing',  'Beijing'),

(2222, '2024-01-02 00:00:00', 'registration', 'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:00', 'logon',        'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:01', 'payment',      'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:03', 'payment',      'Zhejiang', 'Hangzhou'),

(3333, '2024-01-02 00:00:00', 'registration', 'Shanghai', 'Shanghai'),
(3333, '2024-01-02 00:00:00', 'logon',        'Shanghai', 'Shanghai'),
(3333, '2024-01-02 00:00:01', 'payment',      'Shanghai', 'Shanghai'),
(3333, '2024-01-02 00:00:03', 'payment',      'Shanghai', 'Shanghai'),
(3333, '2024-01-02 00:00:04', 'exit',         'Shanghai', 'Shanghai');

Step 2: Query daily funnel data grouped by province.

SELECT
    key,
    funnel_rep(3, 4, res) AS ans
FROM (
    SELECT
        id,
        finder_group_funnel_text_group(result) AS key,
        finder_group_funnel_res(result) AS res
    FROM (
        SELECT
            id,
            UNNEST(
                finder_group_funnel(
                    86400000 * 3,
                    EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
                    86400, 3, 4, 0, 1, 'Asia/Shanghai', FALSE,
                    event_time, event_time,
                    province,
                    event = 'Register',
                    event = 'Log on',
                    event = 'Payment',
                    event = 'Exit'
                )
            ) AS result
        FROM finder_group_funnel_test_1
        GROUP BY id
    ) a
) b
GROUP BY key;

Result:

   key    |                    ans
----------+-------------------------------------------
 Beijing  | {"1,1,1,1","1,1,1,1","1,1,1,0","1,1,0,0"}
 unreach  | {"0,0,0,0","0,0,0,0","0,0,0,0","0,0,0,0"}
 Shanghai | {"1,1,1,1","1,1,1,1","0,0,0,0","0,0,0,0"}
 Zhejiang | {"1,1,1,0","1,1,1,0","0,0,0,0","0,0,0,0"}
(4 rows)

Beijing's user completed all 4 events on day 1 and continued converting on days 2 and 3. Shanghai's user also completed all 4 events but only on day 1 (no follow-up activity). Zhejiang's user reached only 3 of 4 events.

Scenario 2: Group funnel results by calendar day

Goal: The same team wants to observe funnel data aligned to calendar-day boundaries (midnight to midnight) rather than a rolling elapsed-time window. This matches how business reporting periods are typically defined. With a rolling window, the exit event on 2024-01-05 might still fall within 3 days of the first event; with calendar-day boundaries, it does not.

Step 1: Create the test table and insert data.

CREATE TABLE finder_group_funnel_test_2(
  id INT,
  event_time TIMESTAMP,
  event TEXT,
  province TEXT,
  city TEXT
);

INSERT INTO finder_group_funnel_test_2 VALUES
(1111, '2024-01-02 00:00:02', 'registration', 'Beijing',  'Beijing'),
(1111, '2024-01-02 00:00:03', 'logon',        'Beijing',  'Beijing'),

(1111, '2024-01-03 00:00:04', 'payment',      'Beijing',  'Beijing'),

(1111, '2024-01-05 00:00:01', 'exit',         'Beijing',  'Beijing'),

(2222, '2024-01-02 00:00:00', 'registration', 'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:00', 'logon',        'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:01', 'payment',      'Zhejiang', 'Hangzhou'),
(2222, '2024-01-02 00:00:03', 'payment',      'Zhejiang', 'Hangzhou');

Step 2: Query with calendar-day boundaries (`is_relative_window=TRUE`).

SELECT
    key,
    funnel_rep(3, 4, res) AS ans
FROM (
    SELECT
        id,
        finder_group_funnel_text_group(result) AS key,
        finder_group_funnel_res(result) AS res
    FROM (
        SELECT
            id,
            UNNEST(
                finder_group_funnel(
                    86400000 * 3,
                    EXTRACT(epoch FROM TIMESTAMP '2024-01-02 00:00:00')::BIGINT,
                    86400, 3, 4, 0, 1, 'Asia/Shanghai', TRUE, -- calendar-day window
                    event_time, event_time,
                    province,
                    event = 'register',
                    event = 'logon',
                    event = 'pay',
                    event = 'exit'
                )
            ) AS result
        FROM finder_group_funnel_test_2
        GROUP BY id
    ) a
) b
GROUP BY key;

Result:

   key    |                    ans
----------+-------------------------------------------
 unreach  | {"0,0,0,0","0,0,0,0","0,0,0,0","0,0,0,0"}
 Zhejiang | {"1,1,1,0","1,1,1,0","0,0,0,0","0,0,0,0"}
 Beijing  | {"1,1,1,0","1,1,1,0","0,0,0,0","0,0,0,0"}
(3 rows)

With calendar-day boundaries, user 1111 (Beijing) completes only 3 of 4 events within the 3-day window. Their exit event occurs on 2024-01-05, which falls outside the calendar-day window starting 2024-01-02 (covering January 2, 3, and 4). Under a rolling window, the same event would be captured because it falls within 3 × 86,400 seconds of the first event.

Limitations

LimitationDetails
Version requirementOnly Hologres V2.2.32 and later support finder_group_funnel.
group_dimension field typeOnly TEXT fields are supported. To group by multiple fields, use concat_ws or concat.
Calendar-day window constraintsWhen is_relative_window=true, window must be an integer multiple of 86,400,000 and step_interval must be 86400.
Extension schemaThe flow_analysis extension loads into the public schema only and cannot be loaded into other schemas.