chore: remove queries scratch file

This commit is contained in:
Shivam Mishra
2026-06-30 19:04:07 +05:30
parent 67f55c5b7f
commit 76dc037c1a
-214
View File
@@ -1,214 +0,0 @@
# Captain Overview — effective SQL per stat
These are the queries `Captain::AssistantStatsBuilder` effectively runs for
`account_id = 1`, `assistant_id = 1`, over a **30-day current window**
(`created_at >= NOW() - INTERVAL '30 days'`). Each metric runs once for the
current window and once for the previous equal-length window
(`NOW() - INTERVAL '60 days'` to `NOW() - INTERVAL '30 days'`); only the current
window is shown below. Swap the interval bounds for the previous window.
Knowledge stats are point-in-time (no window, no previous).
---
## 1. Conversations handled
Distinct conversations the assistant authored any message in.
```sql
SELECT COUNT(DISTINCT conversation_id)
FROM messages
WHERE account_id = 1
AND sender_type = 'Captain::Assistant'
AND sender_id = 1
AND created_at >= NOW() - INTERVAL '30 days';
```
Indexes that matter: `messages (account_id, ...)`, plus the `sender_type/sender_id`
filter. This is the "handled set" reused as a subquery by stats 2 and 3.
---
## 2 & 3. Auto-resolution rate + handoff rate (combined)
`auto_resolution = resolved / handled * 100` and `handoff = handoff / handled * 100`
share the same handled-set subquery, so they fold into a single pass with
conditional aggregation. This runs the (costly) `messages` handled-set subquery
**once** and scans `reporting_events` once, instead of twice each.
```sql
SELECT
COUNT(DISTINCT conversation_id)
FILTER (WHERE name IN ('conversation_captain_inference_resolved',
'conversation_bot_resolved')) AS resolved,
COUNT(DISTINCT conversation_id)
FILTER (WHERE name IN ('conversation_captain_inference_handoff',
'conversation_bot_handoff')) AS handoff
FROM reporting_events
WHERE account_id = 1
AND name IN ('conversation_captain_inference_resolved', 'conversation_bot_resolved',
'conversation_captain_inference_handoff', 'conversation_bot_handoff')
AND conversation_id IN (
SELECT conversation_id
FROM messages
WHERE account_id = 1
AND sender_type = 'Captain::Assistant'
AND sender_id = 1
AND created_at >= NOW() - INTERVAL '30 days'
);
```
The rates are still computed in Ruby (`resolved / handled`, `handoff / handled`),
so divide-by-zero guarding stays in the builder. The two rates do **not** sum to
100%: a handled conversation may carry neither event (still open) or both
(handed off then later resolved).
Note: the event rows themselves are **not** date-filtered; the window is applied
via the handled-set subquery (the conversations the assistant touched in the
window).
### Optional: fold in "handled" too (one query for all three)
Materialize the handled set once in a CTE and derive all three numbers from it.
Useful because the page also displays `handled`, and every metric runs for both
the current and previous window.
```sql
WITH handled AS (
SELECT DISTINCT conversation_id
FROM messages
WHERE account_id = 1
AND sender_type = 'Captain::Assistant'
AND sender_id = 1
AND created_at >= NOW() - INTERVAL '30 days'
)
SELECT
(SELECT COUNT(*) FROM handled) AS handled,
COUNT(DISTINCT re.conversation_id)
FILTER (WHERE re.name IN ('conversation_captain_inference_resolved',
'conversation_bot_resolved')) AS resolved,
COUNT(DISTINCT re.conversation_id)
FILTER (WHERE re.name IN ('conversation_captain_inference_handoff',
'conversation_bot_handoff')) AS handoff
FROM reporting_events re
JOIN handled h ON h.conversation_id = re.conversation_id
WHERE re.account_id = 1
AND re.name IN ('conversation_captain_inference_resolved', 'conversation_bot_resolved',
'conversation_captain_inference_handoff', 'conversation_bot_handoff');
```
Keep `handled` sourced from the CTE count (not `COUNT(*)` over the join), so
conversations with no event row still count toward `handled`.
---
## 4. Hours saved
`public_outgoing_count * avg_reply_time_seconds / 3600`, rounded. Two queries.
Public outgoing replies the assistant sent:
```sql
SELECT COUNT(*)
FROM messages
WHERE account_id = 1
AND sender_type = 'Captain::Assistant'
AND sender_id = 1
AND message_type = 1 -- outgoing
AND private = false
AND created_at >= NOW() - INTERVAL '30 days';
```
Average reply time across the account in the window (seconds):
```sql
SELECT AVG(value)
FROM reporting_events
WHERE account_id = 1
AND name = 'reply_time'
AND created_at >= NOW() - INTERVAL '30 days';
```
---
## 5. Conversation depth (messages / conversation)
`public_outgoing_count / distinct_conversations`. Reuses query 4's count plus:
```sql
SELECT COUNT(DISTINCT conversation_id)
FROM messages
WHERE account_id = 1
AND sender_type = 'Captain::Assistant'
AND sender_id = 1
AND message_type = 1 -- outgoing
AND private = false
AND created_at >= NOW() - INTERVAL '30 days';
```
---
## 6. Reopen-after-resolve rate
`reopened / resolved * 100`, where "resolved" is the inbox-based Captain-resolved
set. Two queries.
Resolved (inbox-scoped) in the window:
```sql
SELECT COUNT(DISTINCT conversation_id)
FROM reporting_events
WHERE account_id = 1
AND name = 'conversation_captain_inference_resolved'
AND inbox_id IN (
SELECT inbox_id FROM captain_inboxes WHERE captain_assistant_id = 1
)
AND created_at >= NOW() - INTERVAL '30 days';
```
Of those, the ones later reopened (`conversation_opened` with `value > 0`):
```sql
SELECT COUNT(DISTINCT conversation_id)
FROM reporting_events
WHERE account_id = 1
AND name = 'conversation_opened'
AND value > 0
AND conversation_id IN (
SELECT conversation_id
FROM reporting_events
WHERE account_id = 1
AND name = 'conversation_captain_inference_resolved'
AND inbox_id IN (
SELECT inbox_id FROM captain_inboxes WHERE captain_assistant_id = 1
)
AND created_at >= NOW() - INTERVAL '30 days'
);
```
Note: the `conversation_opened` events are **not** date-filtered; a reopen counts
whenever it happened, as long as the resolve fell in the window.
---
## 7. Knowledge (point-in-time, no window)
Approved / pending FAQ counts:
```sql
SELECT status, COUNT(*)
FROM captain_assistant_responses
WHERE assistant_id = 1
GROUP BY status;
-- status: 0 = pending, 1 = approved
```
Document count:
```sql
SELECT COUNT(*)
FROM captain_documents
WHERE assistant_id = 1;
```
`coverage = approved / (approved + pending) * 100`, computed in Ruby.