From 959b17f74cd4d5713ff629ed79ce5d8752ca038f Mon Sep 17 00:00:00 2001 From: Sandy Spicer Date: Wed, 11 Sep 2024 08:52:20 -0700 Subject: [PATCH] fix: retention query returns wrong results with target_first_time (#24901) --- .../insights/retention_query_runner.py | 7 ++- .../test/test_retention_query_runner.py | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/posthog/hogql_queries/insights/retention_query_runner.py b/posthog/hogql_queries/insights/retention_query_runner.py index f5d817e2eb7f8..9bbb21e109a19 100644 --- a/posthog/hogql_queries/insights/retention_query_runner.py +++ b/posthog/hogql_queries/insights/retention_query_runner.py @@ -170,7 +170,12 @@ def actor_query(self, breakdown_values_filter: Optional[int] = None) -> ast.Sele { "target_timestamps": target_timestamps, "min_timestamp": self.query_date_range.date_to_start_of_interval_hogql( - parse_expr("min(events.timestamp)") + parse_expr( + "minIf(events.timestamp, {target_entity_expr})", + { + "target_entity_expr": target_entity_expr, + }, + ) ), }, ) diff --git a/posthog/hogql_queries/insights/test/test_retention_query_runner.py b/posthog/hogql_queries/insights/test/test_retention_query_runner.py index 7e096d7a9ab64..bc97e8b7d51d3 100644 --- a/posthog/hogql_queries/insights/test/test_retention_query_runner.py +++ b/posthog/hogql_queries/insights/test/test_retention_query_runner.py @@ -907,6 +907,64 @@ def test_all_events(self): ], ) + def test_all_events_target_first_time(self): + _create_person(team_id=self.team.pk, distinct_ids=["person1"]) + + _create_events( + self.team, + [ + ("person1", _date(0)), + ("person1", _date(1)), + ("person1", _date(2)), + ], + "event1", + ) + + _create_events( + self.team, + [ + ("person1", _date(2)), + ("person1", _date(3)), + ], + "event2", + ) + + result_all_events = self.run_query( + query={ + "dateRange": {"date_to": _date(2, hour=6)}, + "retentionFilter": { + "retentionType": "retention_first_time", + "totalIntervals": 4, + "targetEntity": {"id": "event2", "type": "events"}, + "returningEntity": {"id": None, "name": "All events"}, + }, + } + ) + + result_specific_event = self.run_query( + query={ + "dateRange": {"date_to": _date(2, hour=6)}, + "retentionFilter": { + "retentionType": "retention_first_time", + "totalIntervals": 4, + "targetEntity": {"id": "event2", "type": "events"}, + "returningEntity": {"id": "event2", "type": "events"}, + }, + } + ) + + self.assertEqual( + pluck(result_specific_event, "values", "count"), + [ + [0, 0, 0, 0], + [0, 0, 0], + [0, 0], + [1], + ], + ) + + self.assertEqual(result_specific_event, result_all_events) + def test_retention_people_basic(self): person1 = _create_person(team_id=self.team.pk, distinct_ids=["person1", "alias1"]) _create_person(team_id=self.team.pk, distinct_ids=["person2"])