@hailer/mcp 1.1.16 → 1.1.17-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +117 -320
- package/.claude/commands/app-squad.md +86 -90
- package/.claude/commands/audit-squad.md +19 -19
- package/.claude/commands/autoplan.md +3 -3
- package/.claude/commands/cleanup-squad.md +16 -16
- package/.claude/commands/config-squad.md +30 -30
- package/.claude/commands/crud-squad.md +23 -23
- package/.claude/commands/data-squad.md +21 -21
- package/.claude/commands/debug-squad.md +44 -44
- package/.claude/commands/doc-squad.md +16 -16
- package/.claude/commands/help:agents.md +130 -99
- package/.claude/commands/help:commands.md +15 -15
- package/.claude/commands/help:faq.md +17 -17
- package/.claude/commands/help:plugins.md +1 -1
- package/.claude/commands/help:skills.md +18 -24
- package/.claude/commands/hotfix-squad.md +22 -22
- package/.claude/commands/integration-squad.md +22 -22
- package/.claude/commands/janitor-squad.md +31 -31
- package/.claude/commands/learn-auto.md +5 -5
- package/.claude/commands/learn.md +12 -20
- package/.claude/commands/onboard-squad.md +39 -49
- package/.claude/commands/plan-workspace.md +2 -2
- package/.claude/commands/publish.md +32 -37
- package/.claude/commands/review-squad.md +27 -27
- package/.claude/commands/stats.md +26 -12
- package/.claude/commands/swarm.md +25 -25
- package/.claude/skills/chrome-mcp-reference/SKILL.md +5 -0
- package/.claude/skills/hailer-api-client/SKILL.md +55 -16
- package/.claude/skills/hailer-app-builder/SKILL.md +4 -270
- package/.claude/skills/hailer-apps-pictures/SKILL.md +3 -3
- package/.claude/skills/hailer-design-system/SKILL.md +96 -4
- package/.claude/skills/hailer-monolith-automations/SKILL.md +138 -116
- package/.claude/skills/hailer-permissions-system/SKILL.md +6 -9
- package/.claude/skills/hailer-project-protocol/SKILL.md +20 -110
- package/.claude/skills/integration-patterns/SKILL.md +6 -6
- package/.claude/skills/lsp-setup/SKILL.md +8 -9
- package/.claude/skills/sdk-activity-patterns/SKILL.md +238 -0
- package/.claude/skills/{SDK-document-templates → sdk-document-templates}/SKILL.md +13 -340
- package/.claude/skills/{SDK-function-fields → sdk-function-fields}/SKILL.md +8 -40
- package/.claude/skills/{SDK-insight-queries → sdk-insight-queries}/SKILL.md +114 -392
- package/.claude/skills/{SDK-ws-config-skill → sdk-ws-config-skill}/SKILL.md +79 -310
- package/.claude/skills/zapier-hailer-patterns/SKILL.md +84 -361
- package/.opencode/package-lock.json +117 -0
- package/CLAUDE.md +5 -358
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +10 -127
- package/dist/app.js.map +1 -1
- package/dist/bot/bot-manager.d.ts +3 -14
- package/dist/bot/bot-manager.d.ts.map +1 -1
- package/dist/bot/bot-manager.js +13 -4
- package/dist/bot/bot-manager.js.map +1 -1
- package/dist/bot/bot.d.ts +23 -102
- package/dist/bot/bot.d.ts.map +1 -1
- package/dist/bot/bot.js +356 -1212
- package/dist/bot/bot.js.map +1 -1
- package/dist/bot/services/bot-permissions.d.ts +50 -0
- package/dist/bot/services/bot-permissions.d.ts.map +1 -0
- package/dist/bot/services/bot-permissions.js +198 -0
- package/dist/bot/services/bot-permissions.js.map +1 -0
- package/dist/bot/services/index.d.ts +4 -2
- package/dist/bot/services/index.d.ts.map +1 -1
- package/dist/bot/services/index.js +10 -5
- package/dist/bot/services/index.js.map +1 -1
- package/dist/bot/services/message-classifier.d.ts +1 -1
- package/dist/bot/services/message-classifier.d.ts.map +1 -1
- package/dist/bot/services/message-classifier.js.map +1 -1
- package/dist/bot/services/signal-router.d.ts +32 -0
- package/dist/bot/services/signal-router.d.ts.map +1 -0
- package/dist/bot/services/signal-router.js +132 -0
- package/dist/bot/services/signal-router.js.map +1 -0
- package/dist/bot/services/system-prompt.d.ts +12 -0
- package/dist/bot/services/system-prompt.d.ts.map +1 -0
- package/dist/bot/services/system-prompt.js +93 -0
- package/dist/bot/services/system-prompt.js.map +1 -0
- package/dist/bot/services/types.d.ts +7 -34
- package/dist/bot/services/types.d.ts.map +1 -1
- package/dist/bot/services/types.js +0 -3
- package/dist/bot/services/types.js.map +1 -1
- package/dist/bot/services/workspace-refresh.d.ts +47 -0
- package/dist/bot/services/workspace-refresh.d.ts.map +1 -0
- package/dist/bot/services/workspace-refresh.js +154 -0
- package/dist/bot/services/workspace-refresh.js.map +1 -0
- package/dist/bot-config/constants.d.ts +0 -36
- package/dist/bot-config/constants.d.ts.map +1 -1
- package/dist/bot-config/constants.js +1 -76
- package/dist/bot-config/constants.js.map +1 -1
- package/dist/bot-config/context.d.ts +2 -42
- package/dist/bot-config/context.d.ts.map +1 -1
- package/dist/bot-config/context.js +13 -134
- package/dist/bot-config/context.js.map +1 -1
- package/dist/bot-config/index.d.ts +6 -15
- package/dist/bot-config/index.d.ts.map +1 -1
- package/dist/bot-config/index.js +5 -80
- package/dist/bot-config/index.js.map +1 -1
- package/dist/bot-config/loader.d.ts +16 -4
- package/dist/bot-config/loader.d.ts.map +1 -1
- package/dist/bot-config/loader.js +187 -96
- package/dist/bot-config/loader.js.map +1 -1
- package/dist/bot-config/persistence.d.ts +1 -52
- package/dist/bot-config/persistence.d.ts.map +1 -1
- package/dist/bot-config/persistence.js +3 -213
- package/dist/bot-config/persistence.js.map +1 -1
- package/dist/bot-config/state.d.ts +0 -41
- package/dist/bot-config/state.d.ts.map +1 -1
- package/dist/bot-config/state.js +0 -151
- package/dist/bot-config/state.js.map +1 -1
- package/dist/bot-config/tools.d.ts +1 -1
- package/dist/bot-config/tools.js +27 -27
- package/dist/bot-config/tools.js.map +1 -1
- package/dist/bot-config/types.d.ts +39 -32
- package/dist/bot-config/types.d.ts.map +1 -1
- package/dist/bot-config/types.js +0 -3
- package/dist/bot-config/types.js.map +1 -1
- package/dist/bot-config/webhooks.d.ts +0 -4
- package/dist/bot-config/webhooks.d.ts.map +1 -1
- package/dist/bot-config/webhooks.js +0 -13
- package/dist/bot-config/webhooks.js.map +1 -1
- package/dist/commands/seed-config.js +16 -31
- package/dist/commands/seed-config.js.map +1 -1
- package/dist/config.d.ts +0 -9
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -15
- package/dist/config.js.map +1 -1
- package/dist/mcp/hailer-clients.js +2 -2
- package/dist/mcp/hailer-clients.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts +10 -115
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +39 -363
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/mcp/tools/activity.d.ts +3 -0
- package/dist/mcp/tools/activity.d.ts.map +1 -1
- package/dist/mcp/tools/activity.js +8 -1
- package/dist/mcp/tools/activity.js.map +1 -1
- package/dist/mcp/tools/app-core.d.ts +3 -0
- package/dist/mcp/tools/app-core.d.ts.map +1 -1
- package/dist/mcp/tools/app-core.js +9 -2
- package/dist/mcp/tools/app-core.js.map +1 -1
- package/dist/mcp/tools/app-marketplace.d.ts +3 -0
- package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
- package/dist/mcp/tools/app-marketplace.js +13 -1
- package/dist/mcp/tools/app-marketplace.js.map +1 -1
- package/dist/mcp/tools/app-member.d.ts +3 -0
- package/dist/mcp/tools/app-member.d.ts.map +1 -1
- package/dist/mcp/tools/app-member.js +6 -1
- package/dist/mcp/tools/app-member.js.map +1 -1
- package/dist/mcp/tools/app-scaffold.d.ts +3 -0
- package/dist/mcp/tools/app-scaffold.d.ts.map +1 -1
- package/dist/mcp/tools/app-scaffold.js +19 -11
- package/dist/mcp/tools/app-scaffold.js.map +1 -1
- package/dist/mcp/tools/company.d.ts +3 -0
- package/dist/mcp/tools/company.d.ts.map +1 -1
- package/dist/mcp/tools/company.js +5 -1
- package/dist/mcp/tools/company.js.map +1 -1
- package/dist/mcp/tools/discussion.d.ts +3 -0
- package/dist/mcp/tools/discussion.d.ts.map +1 -1
- package/dist/mcp/tools/discussion.js +13 -2
- package/dist/mcp/tools/discussion.js.map +1 -1
- package/dist/mcp/tools/file.d.ts +3 -0
- package/dist/mcp/tools/file.d.ts.map +1 -1
- package/dist/mcp/tools/file.js +6 -1
- package/dist/mcp/tools/file.js.map +1 -1
- package/dist/mcp/tools/index.d.ts +7 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +34 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/insight.d.ts +3 -0
- package/dist/mcp/tools/insight.d.ts.map +1 -1
- package/dist/mcp/tools/insight.js +18 -8
- package/dist/mcp/tools/insight.js.map +1 -1
- package/dist/mcp/tools/user.d.ts +3 -0
- package/dist/mcp/tools/user.d.ts.map +1 -1
- package/dist/mcp/tools/user.js +6 -1
- package/dist/mcp/tools/user.js.map +1 -1
- package/dist/mcp/tools/workflow-permissions.d.ts +3 -0
- package/dist/mcp/tools/workflow-permissions.d.ts.map +1 -1
- package/dist/mcp/tools/workflow-permissions.js +8 -1
- package/dist/mcp/tools/workflow-permissions.js.map +1 -1
- package/dist/mcp/tools/workflow.d.ts +3 -0
- package/dist/mcp/tools/workflow.d.ts.map +1 -1
- package/dist/mcp/tools/workflow.js +29 -28
- package/dist/mcp/tools/workflow.js.map +1 -1
- package/dist/mcp/utils/index.d.ts +4 -11
- package/dist/mcp/utils/index.d.ts.map +1 -1
- package/dist/mcp/utils/index.js +5 -36
- package/dist/mcp/utils/index.js.map +1 -1
- package/dist/mcp/utils/role-utils.d.ts +0 -32
- package/dist/mcp/utils/role-utils.d.ts.map +1 -1
- package/dist/mcp/utils/role-utils.js +0 -73
- package/dist/mcp/utils/role-utils.js.map +1 -1
- package/dist/mcp/utils/tool-helpers.d.ts +0 -25
- package/dist/mcp/utils/tool-helpers.d.ts.map +1 -1
- package/dist/mcp/utils/tool-helpers.js +0 -34
- package/dist/mcp/utils/tool-helpers.js.map +1 -1
- package/dist/mcp/webhook-handler.d.ts +4 -34
- package/dist/mcp/webhook-handler.d.ts.map +1 -1
- package/dist/mcp/webhook-handler.js +57 -74
- package/dist/mcp/webhook-handler.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +3 -78
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -2
- package/.claude/agents/agent-ada-skill-builder.md +0 -94
- package/.claude/agents/agent-alejandro-function-fields.md +0 -342
- package/.claude/agents/agent-bjorn-config-audit.md +0 -103
- package/.claude/agents/agent-builder-agent-creator.md +0 -130
- package/.claude/agents/agent-code-simplifier.md +0 -53
- package/.claude/agents/agent-dmitri-activity-crud.md +0 -159
- package/.claude/agents/agent-giuseppe-app-builder.md +0 -208
- package/.claude/agents/agent-gunther-mcp-tools.md +0 -39
- package/.claude/agents/agent-helga-workflow-config.md +0 -204
- package/.claude/agents/agent-igor-activity-mover-automation.md +0 -125
- package/.claude/agents/agent-ingrid-doc-templates.md +0 -261
- package/.claude/agents/agent-ivan-monolith.md +0 -154
- package/.claude/agents/agent-kenji-data-reader.md +0 -86
- package/.claude/agents/agent-lars-code-inspector.md +0 -102
- package/.claude/agents/agent-marco-mockup-builder.md +0 -110
- package/.claude/agents/agent-marcus-api-documenter.md +0 -323
- package/.claude/agents/agent-marketplace-publisher.md +0 -280
- package/.claude/agents/agent-marketplace-reviewer.md +0 -309
- package/.claude/agents/agent-permissions-handler.md +0 -208
- package/.claude/agents/agent-simple-writer.md +0 -48
- package/.claude/agents/agent-svetlana-code-review.md +0 -171
- package/.claude/agents/agent-tanya-test-runner.md +0 -333
- package/.claude/agents/agent-ui-designer.md +0 -100
- package/.claude/agents/agent-viktor-sql-insights.md +0 -212
- package/.claude/agents/agent-web-search.md +0 -55
- package/.claude/agents/agent-yevgeni-discussions.md +0 -45
- package/.claude/agents/agent-zara-zapier.md +0 -159
- package/.claude/skills/SDK-activity-patterns/SKILL.md +0 -428
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -92
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -127
- package/.claude/skills/agent-structure/SKILL.md +0 -98
- package/.claude/skills/delegation-routing/SKILL.md +0 -202
- package/.claude/skills/frontend-design/SKILL.md +0 -254
- package/.claude/skills/hailer-activity-mover/SKILL.md +0 -213
- package/.claude/skills/hailer-rest-api/SKILL.md +0 -61
- package/.claude/skills/hailer-rest-api/hailer-activities.md +0 -184
- package/.claude/skills/hailer-rest-api/hailer-admin.md +0 -473
- package/.claude/skills/hailer-rest-api/hailer-calendar.md +0 -256
- package/.claude/skills/hailer-rest-api/hailer-feed.md +0 -249
- package/.claude/skills/hailer-rest-api/hailer-insights.md +0 -195
- package/.claude/skills/hailer-rest-api/hailer-messaging.md +0 -276
- package/.claude/skills/hailer-rest-api/hailer-workflows.md +0 -283
- package/.claude/skills/insight-join-patterns/SKILL.md +0 -174
- package/.claude/skills/json-only-output/SKILL.md +0 -72
- package/.claude/skills/mcp-direct-tools/SKILL.md +0 -153
- package/.claude/skills/optional-parameters/SKILL.md +0 -72
- package/.claude/skills/tool-parameter-usage/SKILL.md +0 -126
- package/.claude/skills/tool-response-verification/SKILL.md +0 -92
- package/.opencode/agent/agent-ada-skill-builder.md +0 -35
- package/.opencode/agent/agent-alejandro-function-fields.md +0 -39
- package/.opencode/agent/agent-bjorn-config-audit.md +0 -36
- package/.opencode/agent/agent-builder-agent-creator.md +0 -39
- package/.opencode/agent/agent-code-simplifier.md +0 -31
- package/.opencode/agent/agent-dmitri-activity-crud.md +0 -40
- package/.opencode/agent/agent-giuseppe-app-builder.md +0 -37
- package/.opencode/agent/agent-gunther-mcp-tools.md +0 -39
- package/.opencode/agent/agent-helga-workflow-config.md +0 -204
- package/.opencode/agent/agent-igor-activity-mover-automation.md +0 -46
- package/.opencode/agent/agent-ingrid-doc-templates.md +0 -39
- package/.opencode/agent/agent-ivan-monolith.md +0 -46
- package/.opencode/agent/agent-kenji-data-reader.md +0 -53
- package/.opencode/agent/agent-lars-code-inspector.md +0 -28
- package/.opencode/agent/agent-marco-mockup-builder.md +0 -42
- package/.opencode/agent/agent-marcus-api-documenter.md +0 -53
- package/.opencode/agent/agent-marketplace-publisher.md +0 -44
- package/.opencode/agent/agent-marketplace-reviewer.md +0 -42
- package/.opencode/agent/agent-permissions-handler.md +0 -50
- package/.opencode/agent/agent-simple-writer.md +0 -45
- package/.opencode/agent/agent-svetlana-code-review.md +0 -39
- package/.opencode/agent/agent-tanya-test-runner.md +0 -57
- package/.opencode/agent/agent-ui-designer.md +0 -56
- package/.opencode/agent/agent-viktor-sql-insights.md +0 -34
- package/.opencode/agent/agent-web-search.md +0 -42
- package/.opencode/agent/agent-yevgeni-discussions.md +0 -37
- package/.opencode/agent/agent-zara-zapier.md +0 -53
- package/.opencode/commands/app-squad.md +0 -135
- package/.opencode/commands/audit-squad.md +0 -158
- package/.opencode/commands/autoplan.md +0 -563
- package/.opencode/commands/cleanup-squad.md +0 -98
- package/.opencode/commands/config-squad.md +0 -106
- package/.opencode/commands/crud-squad.md +0 -87
- package/.opencode/commands/data-squad.md +0 -97
- package/.opencode/commands/debug-squad.md +0 -303
- package/.opencode/commands/doc-squad.md +0 -65
- package/.opencode/commands/handoff.md +0 -137
- package/.opencode/commands/health.md +0 -49
- package/.opencode/commands/help-agents.md +0 -151
- package/.opencode/commands/help-commands.md +0 -32
- package/.opencode/commands/help-faq.md +0 -29
- package/.opencode/commands/help-plugins.md +0 -28
- package/.opencode/commands/help-skills.md +0 -7
- package/.opencode/commands/help-tools.md +0 -40
- package/.opencode/commands/help.md +0 -28
- package/.opencode/commands/hotfix-squad.md +0 -112
- package/.opencode/commands/integration-squad.md +0 -82
- package/.opencode/commands/janitor-squad.md +0 -167
- package/.opencode/commands/learn-auto.md +0 -120
- package/.opencode/commands/learn.md +0 -120
- package/.opencode/commands/mcp-list.md +0 -27
- package/.opencode/commands/onboard-squad.md +0 -140
- package/.opencode/commands/plan-workspace.md +0 -732
- package/.opencode/commands/prd.md +0 -131
- package/.opencode/commands/project-status.md +0 -82
- package/.opencode/commands/publish.md +0 -138
- package/.opencode/commands/recap.md +0 -69
- package/.opencode/commands/restore.md +0 -64
- package/.opencode/commands/review-squad.md +0 -152
- package/.opencode/commands/save.md +0 -24
- package/.opencode/commands/stats.md +0 -19
- package/.opencode/commands/swarm.md +0 -210
- package/.opencode/commands/tool-builder.md +0 -39
- package/.opencode/commands/ws-pull.md +0 -44
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: SQL query patterns for Hailer insights - aggregations, filtering, dates, CASE statements
|
|
4
|
-
version: 1.
|
|
5
|
-
triggers: Insight queries, GROUP BY, COUNT, SUM, date formatting, CASE WHEN
|
|
2
|
+
name: sdk-insight-queries
|
|
3
|
+
description: SQL query patterns for Hailer insights - aggregations, filtering, dates, CASE statements, cross-workflow JOINs
|
|
4
|
+
version: 1.6.0
|
|
5
|
+
triggers: Insight queries, GROUP BY, COUNT, SUM, date formatting, CASE WHEN, JOIN query errors, missing columns, NULL results in insight queries
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Insight Query Patterns
|
|
@@ -112,11 +112,6 @@ fields: [
|
|
|
112
112
|
]
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
Benefits of real names:
|
|
116
|
-
- Queries are readable and self-documenting
|
|
117
|
-
- Field names match Hailer UI labels
|
|
118
|
-
- Easier debugging and maintenance
|
|
119
|
-
|
|
120
115
|
---
|
|
121
116
|
|
|
122
117
|
## Available Meta Fields
|
|
@@ -139,93 +134,12 @@ Benefits of real names:
|
|
|
139
134
|
|
|
140
135
|
---
|
|
141
136
|
|
|
142
|
-
## Aggregations
|
|
143
|
-
|
|
144
|
-
### COUNT
|
|
145
|
-
```sql
|
|
146
|
-
SELECT
|
|
147
|
-
phaseName,
|
|
148
|
-
COUNT(*) as count
|
|
149
|
-
FROM tasks
|
|
150
|
-
GROUP BY phaseName
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### SUM
|
|
154
|
-
```sql
|
|
155
|
-
SELECT
|
|
156
|
-
projectName,
|
|
157
|
-
SUM(hours) as total_hours
|
|
158
|
-
FROM timesheets
|
|
159
|
-
GROUP BY projectName
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### AVG, MIN, MAX
|
|
163
|
-
```sql
|
|
164
|
-
SELECT
|
|
165
|
-
AVG(amount) as avg_amount,
|
|
166
|
-
MIN(amount) as min_amount,
|
|
167
|
-
MAX(amount) as max_amount
|
|
168
|
-
FROM orders
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### COUNT with DISTINCT
|
|
172
|
-
```sql
|
|
173
|
-
SELECT
|
|
174
|
-
COUNT(DISTINCT customerId) as unique_customers
|
|
175
|
-
FROM orders
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
## Filtering
|
|
181
|
-
|
|
182
|
-
### WHERE Clauses
|
|
183
|
-
```sql
|
|
184
|
-
-- Text match
|
|
185
|
-
WHERE priority = "High"
|
|
186
|
-
|
|
187
|
-
-- Numeric comparison
|
|
188
|
-
WHERE amount > 1000
|
|
189
|
-
|
|
190
|
-
-- NULL check
|
|
191
|
-
WHERE assignee IS NOT NULL
|
|
192
|
-
|
|
193
|
-
-- Multiple conditions
|
|
194
|
-
WHERE priority = "High" AND status != "Done"
|
|
195
|
-
|
|
196
|
-
-- IN list
|
|
197
|
-
WHERE phaseName IN ("Todo", "In Progress")
|
|
198
|
-
|
|
199
|
-
-- LIKE pattern
|
|
200
|
-
WHERE title LIKE "%urgent%"
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### HAVING (filter after GROUP BY)
|
|
204
|
-
```sql
|
|
205
|
-
SELECT
|
|
206
|
-
customerId,
|
|
207
|
-
COUNT(*) as order_count
|
|
208
|
-
FROM orders
|
|
209
|
-
GROUP BY customerId
|
|
210
|
-
HAVING COUNT(*) > 5
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
137
|
## Date Handling
|
|
216
138
|
|
|
217
139
|
**CRITICAL:** In Hailer insights, all date/time fields are exposed as **Unix timestamps in SECONDS** (10-digit numbers like `1770050954`).
|
|
218
140
|
|
|
219
141
|
This is different from the Hailer API which uses milliseconds! The insight layer converts automatically.
|
|
220
142
|
|
|
221
|
-
```sql
|
|
222
|
-
-- CORRECT - field is already in seconds, use directly
|
|
223
|
-
strftime('%Y-%m-%d', dateField, 'unixepoch') AS date_formatted
|
|
224
|
-
|
|
225
|
-
-- WRONG - do NOT divide by 1000 (will show wrong dates!)
|
|
226
|
-
strftime('%Y-%m-%d', dateField / 1000, 'unixepoch') AS date_formatted
|
|
227
|
-
```
|
|
228
|
-
|
|
229
143
|
### Range Fields (daterange, datetimerange, timerange)
|
|
230
144
|
|
|
231
145
|
For range field types, Hailer automatically exposes **Start** and **End** suffixes.
|
|
@@ -252,20 +166,16 @@ fields: [
|
|
|
252
166
|
**In queries:** Access with Start/End suffixes (already in seconds):
|
|
253
167
|
```sql
|
|
254
168
|
SELECT
|
|
255
|
-
-- All fields are already in seconds - use directly with strftime
|
|
256
169
|
ajankohtaStart,
|
|
257
170
|
ajankohtaEnd,
|
|
258
171
|
strftime('%d.%m.%Y', ajankohtaStart, 'unixepoch') as start_date,
|
|
259
172
|
strftime('%d.%m.%Y', ajankohtaEnd, 'unixepoch') as end_date,
|
|
260
173
|
|
|
261
174
|
-- Timerange: extract just the time portion
|
|
262
|
-
tyoaikaStart,
|
|
263
|
-
tyoaikaEnd,
|
|
264
175
|
strftime('%H:%M', tyoaikaStart, 'unixepoch') as start_time,
|
|
265
176
|
strftime('%H:%M', tyoaikaEnd, 'unixepoch') as end_time,
|
|
266
177
|
|
|
267
178
|
-- Duration in seconds (both are already seconds)
|
|
268
|
-
(tyoaikaEnd - tyoaikaStart) as duration_seconds,
|
|
269
179
|
(tyoaikaEnd - tyoaikaStart) / 60 as duration_minutes
|
|
270
180
|
FROM events
|
|
271
181
|
WHERE ajankohtaStart >= strftime('%s', 'now')
|
|
@@ -278,16 +188,6 @@ WHERE ajankohtaStart >= strftime('%s', 'now')
|
|
|
278
188
|
- **Data for Hailer apps** → App receives seconds from insight, may need to multiply by 1000 for API calls
|
|
279
189
|
- **Comparisons** → Compare directly with `strftime('%s', ...)` which also returns seconds
|
|
280
190
|
|
|
281
|
-
### Format Date (Finnish)
|
|
282
|
-
```sql
|
|
283
|
-
strftime('%d.%m.%Y', dateField, 'unixepoch') AS date_formatted
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### Format DateTime
|
|
287
|
-
```sql
|
|
288
|
-
strftime('%d.%m.%Y %H:%M', created, 'unixepoch') AS datetime_formatted
|
|
289
|
-
```
|
|
290
|
-
|
|
291
191
|
### Timezone Handling (Finland: +2/+3)
|
|
292
192
|
```sql
|
|
293
193
|
strftime(
|
|
@@ -307,62 +207,11 @@ strftime(
|
|
|
307
207
|
) AS local_time
|
|
308
208
|
```
|
|
309
209
|
|
|
310
|
-
### Filter by Date Range
|
|
311
|
-
```sql
|
|
312
|
-
-- Last 30 days (both sides are seconds)
|
|
313
|
-
WHERE dateField >= strftime('%s', 'now', '-30 days')
|
|
314
|
-
|
|
315
|
-
-- This year
|
|
316
|
-
WHERE strftime('%Y', dateField, 'unixepoch') = strftime('%Y', 'now')
|
|
317
|
-
|
|
318
|
-
-- Specific month
|
|
319
|
-
WHERE strftime('%Y-%m', dateField, 'unixepoch') = '2024-01'
|
|
320
|
-
|
|
321
|
-
-- Between two dates
|
|
322
|
-
WHERE dateField >= strftime('%s', '2024-01-01')
|
|
323
|
-
AND dateField < strftime('%s', '2024-02-01')
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Group by Month
|
|
327
|
-
```sql
|
|
328
|
-
SELECT
|
|
329
|
-
strftime('%Y-%m', created, 'unixepoch') as month,
|
|
330
|
-
COUNT(*) as count
|
|
331
|
-
FROM orders
|
|
332
|
-
GROUP BY strftime('%Y-%m', created, 'unixepoch')
|
|
333
|
-
ORDER BY month
|
|
334
|
-
```
|
|
335
|
-
|
|
336
210
|
---
|
|
337
211
|
|
|
338
212
|
## CASE Statements
|
|
339
213
|
|
|
340
|
-
###
|
|
341
|
-
```sql
|
|
342
|
-
SELECT
|
|
343
|
-
title,
|
|
344
|
-
CASE priority
|
|
345
|
-
WHEN 'High' THEN '🔴'
|
|
346
|
-
WHEN 'Medium' THEN '🟡'
|
|
347
|
-
WHEN 'Low' THEN '🟢'
|
|
348
|
-
ELSE '⚪'
|
|
349
|
-
END as priority_icon
|
|
350
|
-
FROM tasks
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### Searched CASE
|
|
354
|
-
```sql
|
|
355
|
-
SELECT
|
|
356
|
-
title,
|
|
357
|
-
CASE
|
|
358
|
-
WHEN amount > 10000 THEN 'Large'
|
|
359
|
-
WHEN amount > 1000 THEN 'Medium'
|
|
360
|
-
ELSE 'Small'
|
|
361
|
-
END as size_category
|
|
362
|
-
FROM orders
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### CASE in Aggregation
|
|
214
|
+
### CASE in Aggregation (count by status)
|
|
366
215
|
```sql
|
|
367
216
|
SELECT
|
|
368
217
|
SUM(CASE WHEN phaseName = 'Done' THEN 1 ELSE 0 END) as completed,
|
|
@@ -375,28 +224,101 @@ FROM tasks
|
|
|
375
224
|
|
|
376
225
|
## JOINs
|
|
377
226
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
227
|
+
When joining workflows via ActivityLink fields, you must:
|
|
228
|
+
1. Include `_id` meta field in **both** source definitions
|
|
229
|
+
2. Join ON the activitylink field value equals target `_id`
|
|
230
|
+
3. Use the activitylink `fieldId` (NOT the key) in the source definition
|
|
231
|
+
|
|
232
|
+
### Rules
|
|
233
|
+
- Both workflows need `{ name: 'id', meta: '_id' }` in their fields array
|
|
234
|
+
- JOIN condition: `source1.activityLinkFieldName = source2.id`
|
|
235
|
+
- Use LEFT JOIN for optional relationships (activitylink can be null)
|
|
236
|
+
- Use INNER JOIN only when the relationship must exist
|
|
237
|
+
|
|
238
|
+
### Correct Example
|
|
239
|
+
```javascript
|
|
240
|
+
// Players workflow has "club" field (activitylink to Clubs workflow)
|
|
241
|
+
{
|
|
242
|
+
sources: [
|
|
243
|
+
{
|
|
244
|
+
name: 'p',
|
|
245
|
+
workflowId: '68446dc05b30685f67c6fcd4',
|
|
246
|
+
fields: [
|
|
247
|
+
{ name: 'player_name', meta: 'name' },
|
|
248
|
+
{ name: 'id', meta: '_id' }, // Required!
|
|
249
|
+
{ name: 'club', fieldId: '684d5e45...' } // ActivityLink field
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'c',
|
|
254
|
+
workflowId: '691ea936ccb6bdeebc0cbf77',
|
|
255
|
+
fields: [
|
|
256
|
+
{ name: 'club_name', meta: 'name' },
|
|
257
|
+
{ name: 'id', meta: '_id' } // Required!
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
query: 'SELECT p.player_name, c.club_name FROM p LEFT JOIN c ON p.club = c.id'
|
|
262
|
+
}
|
|
385
263
|
```
|
|
386
264
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
265
|
+
### Wrong Example
|
|
266
|
+
```javascript
|
|
267
|
+
// WRONG - Missing _id in clubs source
|
|
268
|
+
{
|
|
269
|
+
sources: [
|
|
270
|
+
{
|
|
271
|
+
name: 'c',
|
|
272
|
+
workflowId: 'clubs-id',
|
|
273
|
+
fields: [
|
|
274
|
+
{ name: 'club_name', meta: 'name' }
|
|
275
|
+
// Missing: { name: 'id', meta: '_id' }
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
],
|
|
279
|
+
query: '... LEFT JOIN c ON p.club = c.id'
|
|
280
|
+
}
|
|
281
|
+
// Error: "no such column: c.id"
|
|
282
|
+
```
|
|
390
283
|
|
|
391
|
-
###
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
284
|
+
### Three-Way JOIN (Tasks -> Topics -> Projects)
|
|
285
|
+
```javascript
|
|
286
|
+
{
|
|
287
|
+
sources: [
|
|
288
|
+
{
|
|
289
|
+
name: 't',
|
|
290
|
+
workflowId: 'tasks-workflow-id',
|
|
291
|
+
fields: [
|
|
292
|
+
{ name: 'task_name', meta: 'name' },
|
|
293
|
+
{ name: 'id', meta: '_id' },
|
|
294
|
+
{ name: 'topic', fieldId: 'topic-field-id' }
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: 'top',
|
|
299
|
+
workflowId: 'topics-workflow-id',
|
|
300
|
+
fields: [
|
|
301
|
+
{ name: 'topic_name', meta: 'name' },
|
|
302
|
+
{ name: 'id', meta: '_id' },
|
|
303
|
+
{ name: 'project', fieldId: 'project-field-id' }
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'p',
|
|
308
|
+
workflowId: 'projects-workflow-id',
|
|
309
|
+
fields: [
|
|
310
|
+
{ name: 'project_name', meta: 'name' },
|
|
311
|
+
{ name: 'id', meta: '_id' }
|
|
312
|
+
]
|
|
313
|
+
}
|
|
314
|
+
],
|
|
315
|
+
query: `
|
|
316
|
+
SELECT t.task_name, top.topic_name, p.project_name
|
|
317
|
+
FROM t
|
|
318
|
+
LEFT JOIN top ON t.topic = top.id
|
|
319
|
+
LEFT JOIN p ON top.project = p.id
|
|
320
|
+
`
|
|
321
|
+
}
|
|
400
322
|
```
|
|
401
323
|
|
|
402
324
|
### User ID → Username Conversion
|
|
@@ -419,126 +341,38 @@ LEFT JOIN user AS m ON m._id = t.manager
|
|
|
419
341
|
-- Each user field needs its own JOIN with unique alias
|
|
420
342
|
LEFT JOIN user AS em ON em._id = t.event_manager
|
|
421
343
|
LEFT JOIN user AS pm ON pm._id = t.production_manager
|
|
422
|
-
LEFT JOIN user AS tm ON tm._id = t.ticketing_manager
|
|
423
344
|
|
|
424
345
|
-- Then select with COALESCE for clean output
|
|
425
346
|
COALESCE(em.name, '') AS Event_Manager,
|
|
426
|
-
COALESCE(pm.name, '') AS Production_Manager
|
|
427
|
-
COALESCE(tm.name, '') AS Ticketing_Manager
|
|
347
|
+
COALESCE(pm.name, '') AS Production_Manager
|
|
428
348
|
```
|
|
429
349
|
|
|
430
350
|
**Why COALESCE?** User fields can be empty - COALESCE returns empty string instead of NULL for cleaner display.
|
|
431
351
|
|
|
432
352
|
**Common mistake:** Trying to add `user` as a source - don't do this! It's built-in.
|
|
433
353
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
---
|
|
437
|
-
|
|
438
|
-
## Sorting & Limiting
|
|
439
|
-
|
|
440
|
-
### ORDER BY
|
|
441
|
-
```sql
|
|
442
|
-
SELECT * FROM tasks
|
|
443
|
-
ORDER BY created DESC
|
|
444
|
-
|
|
445
|
-
-- Multiple columns
|
|
446
|
-
ORDER BY priority ASC, created DESC
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### LIMIT
|
|
450
|
-
```sql
|
|
451
|
-
SELECT * FROM tasks
|
|
452
|
-
ORDER BY created DESC
|
|
453
|
-
LIMIT 10
|
|
454
|
-
|
|
455
|
-
-- With offset (pagination)
|
|
456
|
-
LIMIT 10 OFFSET 20
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
---
|
|
460
|
-
|
|
461
|
-
## String Functions
|
|
462
|
-
|
|
463
|
-
```sql
|
|
464
|
-
-- Concatenate
|
|
465
|
-
SELECT title || ' - ' || phaseName as combined FROM tasks
|
|
466
|
-
|
|
467
|
-
-- Upper/Lower
|
|
468
|
-
SELECT UPPER(title), LOWER(status) FROM tasks
|
|
469
|
-
|
|
470
|
-
-- Substring
|
|
471
|
-
SELECT SUBSTR(title, 1, 50) as short_title FROM tasks
|
|
472
|
-
|
|
473
|
-
-- Replace
|
|
474
|
-
SELECT REPLACE(title, 'OLD', 'NEW') FROM tasks
|
|
475
|
-
|
|
476
|
-
-- Trim
|
|
477
|
-
SELECT TRIM(title) FROM tasks
|
|
354
|
+
### JOIN Troubleshooting
|
|
478
355
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
## NULL Handling
|
|
486
|
-
|
|
487
|
-
```sql
|
|
488
|
-
-- COALESCE (first non-null)
|
|
489
|
-
SELECT COALESCE(assignee, 'Unassigned') as assignee FROM tasks
|
|
490
|
-
|
|
491
|
-
-- IFNULL (SQLite specific)
|
|
492
|
-
SELECT IFNULL(amount, 0) as amount FROM orders
|
|
356
|
+
| Error | Cause | Fix |
|
|
357
|
+
|-------|-------|-----|
|
|
358
|
+
| `no such column: c.id` | Missing `{ name: 'id', meta: '_id' }` in target source | Add `_id` meta to that source |
|
|
359
|
+
| `no such column: p.club` | ActivityLink field not in source fields array | Add field with correct `fieldId` from `get_workflow_schema` |
|
|
360
|
+
| NULL results for joined data | ActivityLink is empty for some activities (expected with LEFT JOIN) | Use INNER JOIN if you only want activities with relationships |
|
|
493
361
|
|
|
494
|
-
|
|
495
|
-
SELECT NULLIF(status, 'None') as status FROM tasks
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
## Subqueries
|
|
501
|
-
|
|
502
|
-
```sql
|
|
503
|
-
-- In WHERE
|
|
504
|
-
SELECT * FROM tasks
|
|
505
|
-
WHERE projectId IN (
|
|
506
|
-
SELECT id FROM projects WHERE status = 'Active'
|
|
507
|
-
)
|
|
362
|
+
### JOIN Checklist
|
|
508
363
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
364
|
+
Before creating an insight with JOINs:
|
|
365
|
+
- [ ] Both workflow sources include `{ name: 'id', meta: '_id' }`
|
|
366
|
+
- [ ] ActivityLink field uses `fieldId` (NOT `key`)
|
|
367
|
+
- [ ] JOIN condition uses column names from sources (e.g., `p.club = c.id`)
|
|
368
|
+
- [ ] Using LEFT JOIN (unless relationship is required)
|
|
369
|
+
- [ ] Tested with `preview_insight` first
|
|
515
370
|
|
|
516
371
|
---
|
|
517
372
|
|
|
518
373
|
## Common Patterns
|
|
519
374
|
|
|
520
|
-
###
|
|
521
|
-
```sql
|
|
522
|
-
SELECT
|
|
523
|
-
phaseName,
|
|
524
|
-
COUNT(*) as count
|
|
525
|
-
FROM tasks
|
|
526
|
-
GROUP BY phaseName
|
|
527
|
-
ORDER BY count DESC
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Sum by Customer
|
|
531
|
-
```sql
|
|
532
|
-
SELECT
|
|
533
|
-
c.name as customer,
|
|
534
|
-
SUM(o.amount) as total
|
|
535
|
-
FROM orders o
|
|
536
|
-
LEFT JOIN customers c ON o.customerId = c.id
|
|
537
|
-
GROUP BY c.name
|
|
538
|
-
ORDER BY total DESC
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
### Monthly Trend
|
|
375
|
+
### Monthly Trend (with seconds-based date)
|
|
542
376
|
```sql
|
|
543
377
|
SELECT
|
|
544
378
|
strftime('%Y-%m', created, 'unixepoch') as month,
|
|
@@ -560,49 +394,8 @@ SELECT
|
|
|
560
394
|
FROM tasks
|
|
561
395
|
```
|
|
562
396
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
## Advanced Patterns
|
|
566
|
-
|
|
567
|
-
### Window Functions
|
|
568
|
-
|
|
569
|
-
Window functions perform calculations across rows without collapsing them (unlike GROUP BY).
|
|
570
|
-
|
|
397
|
+
### Percentage of total (window function)
|
|
571
398
|
```sql
|
|
572
|
-
-- Row numbers (ranking)
|
|
573
|
-
SELECT
|
|
574
|
-
name,
|
|
575
|
-
amount,
|
|
576
|
-
ROW_NUMBER() OVER (ORDER BY amount DESC) as rank
|
|
577
|
-
FROM orders
|
|
578
|
-
|
|
579
|
-
-- Running total
|
|
580
|
-
SELECT
|
|
581
|
-
name,
|
|
582
|
-
amount,
|
|
583
|
-
SUM(amount) OVER (ORDER BY created) as running_total
|
|
584
|
-
FROM orders
|
|
585
|
-
|
|
586
|
-
-- Rank within groups (top 3 per customer)
|
|
587
|
-
SELECT * FROM (
|
|
588
|
-
SELECT
|
|
589
|
-
customerName,
|
|
590
|
-
name,
|
|
591
|
-
amount,
|
|
592
|
-
ROW_NUMBER() OVER (PARTITION BY customerName ORDER BY amount DESC) as rank
|
|
593
|
-
FROM orders
|
|
594
|
-
)
|
|
595
|
-
WHERE rank <= 3
|
|
596
|
-
|
|
597
|
-
-- Compare to previous row
|
|
598
|
-
SELECT
|
|
599
|
-
name,
|
|
600
|
-
amount,
|
|
601
|
-
LAG(amount) OVER (ORDER BY created) as previous_amount,
|
|
602
|
-
amount - LAG(amount) OVER (ORDER BY created) as change
|
|
603
|
-
FROM orders
|
|
604
|
-
|
|
605
|
-
-- Percentage of total
|
|
606
399
|
SELECT
|
|
607
400
|
phaseName,
|
|
608
401
|
COUNT(*) as count,
|
|
@@ -611,28 +404,8 @@ FROM tasks
|
|
|
611
404
|
GROUP BY phaseName
|
|
612
405
|
```
|
|
613
406
|
|
|
614
|
-
|
|
615
|
-
- `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()` - rankings
|
|
616
|
-
- `LAG(col)`, `LEAD(col)` - previous/next row values
|
|
617
|
-
- `SUM() OVER`, `COUNT() OVER`, `AVG() OVER` - running aggregates
|
|
618
|
-
- `FIRST_VALUE()`, `LAST_VALUE()` - boundary values
|
|
619
|
-
- `NTILE(n)` - divide into n buckets
|
|
620
|
-
|
|
621
|
-
### CTEs (WITH Clauses)
|
|
622
|
-
|
|
623
|
-
CTEs make complex queries readable by breaking them into named steps.
|
|
624
|
-
|
|
407
|
+
### CTE with Hailer date functions
|
|
625
408
|
```sql
|
|
626
|
-
-- Simple CTE
|
|
627
|
-
WITH active_orders AS (
|
|
628
|
-
SELECT * FROM orders
|
|
629
|
-
WHERE phaseName != 'Cancelled'
|
|
630
|
-
)
|
|
631
|
-
SELECT customerName, SUM(amount) as total
|
|
632
|
-
FROM active_orders
|
|
633
|
-
GROUP BY customerName
|
|
634
|
-
|
|
635
|
-
-- Multiple CTEs
|
|
636
409
|
WITH
|
|
637
410
|
monthly_sales AS (
|
|
638
411
|
SELECT
|
|
@@ -647,60 +420,11 @@ WITH
|
|
|
647
420
|
SELECT
|
|
648
421
|
ms.month,
|
|
649
422
|
ms.total,
|
|
650
|
-
ma.avg_total,
|
|
651
423
|
CASE WHEN ms.total > ma.avg_total THEN 'Above' ELSE 'Below' END as vs_avg
|
|
652
424
|
FROM monthly_sales ms, monthly_avg ma
|
|
653
425
|
ORDER BY ms.month
|
|
654
|
-
|
|
655
|
-
-- CTE for cleaner JOINs
|
|
656
|
-
WITH
|
|
657
|
-
customer_totals AS (
|
|
658
|
-
SELECT customerId, SUM(amount) as total_spent
|
|
659
|
-
FROM orders
|
|
660
|
-
GROUP BY customerId
|
|
661
|
-
)
|
|
662
|
-
SELECT
|
|
663
|
-
c.name,
|
|
664
|
-
ct.total_spent
|
|
665
|
-
FROM customers c
|
|
666
|
-
LEFT JOIN customer_totals ct ON c.id = ct.customerId
|
|
667
|
-
ORDER BY ct.total_spent DESC
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
### UNION (Combining Results)
|
|
671
|
-
|
|
672
|
-
Combine results from multiple queries.
|
|
673
|
-
|
|
674
|
-
```sql
|
|
675
|
-
-- UNION (removes duplicates)
|
|
676
|
-
SELECT name, 'Task' as type FROM tasks
|
|
677
|
-
UNION
|
|
678
|
-
SELECT name, 'Project' as type FROM projects
|
|
679
|
-
|
|
680
|
-
-- UNION ALL (keeps duplicates, faster)
|
|
681
|
-
SELECT name, amount, 'Invoice' as type FROM invoices
|
|
682
|
-
UNION ALL
|
|
683
|
-
SELECT name, amount, 'Quote' as type FROM quotes
|
|
684
|
-
|
|
685
|
-
-- Combined report from multiple workflows
|
|
686
|
-
SELECT
|
|
687
|
-
'This Month' as period,
|
|
688
|
-
COUNT(*) as count,
|
|
689
|
-
SUM(amount) as total
|
|
690
|
-
FROM orders
|
|
691
|
-
WHERE created >= strftime('%s', 'now', 'start of month')
|
|
692
|
-
UNION ALL
|
|
693
|
-
SELECT
|
|
694
|
-
'Last Month' as period,
|
|
695
|
-
COUNT(*) as count,
|
|
696
|
-
SUM(amount) as total
|
|
697
|
-
FROM orders
|
|
698
|
-
WHERE created >= strftime('%s', 'now', 'start of month', '-1 month')
|
|
699
|
-
AND created < strftime('%s', 'now', 'start of month')
|
|
700
426
|
```
|
|
701
427
|
|
|
702
|
-
**Note:** UNION requires same number of columns with compatible types.
|
|
703
|
-
|
|
704
428
|
---
|
|
705
429
|
|
|
706
430
|
## Testing Queries
|
|
@@ -756,7 +480,6 @@ WHERE created >= strftime('%s', 'now', '-30 days') * 1000
|
|
|
756
480
|
|
|
757
481
|
-- CORRECT (both sides are seconds)
|
|
758
482
|
WHERE created >= strftime('%s', 'now', '-30 days')
|
|
759
|
-
-- 1705312800 >= 1705312800 → correct comparison
|
|
760
483
|
```
|
|
761
484
|
|
|
762
485
|
### Mistake 3: timerange is NOT minutes
|
|
@@ -776,7 +499,6 @@ strftime('%H:%M', created, 'unixepoch')
|
|
|
776
499
|
|
|
777
500
|
-- CORRECT (add timezone offset)
|
|
778
501
|
strftime('%H:%M', created, 'unixepoch', '+2 hours')
|
|
779
|
-
-- Shows "10:30" (or use +3 during summer time)
|
|
780
502
|
```
|
|
781
503
|
|
|
782
504
|
### Quick Debug
|