@bonnard/cli 0.1.3 → 0.1.4
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/dist/bin/bon.mjs +1838 -100
- package/dist/bin/models-IsV2sX74.mjs +76 -0
- package/dist/bin/{validate-Bd1D39Bj.mjs → validate-C4EHvJzJ.mjs} +47 -4
- package/dist/docs/README.md +82 -0
- package/dist/docs/_index.md +69 -0
- package/dist/docs/topics/cubes.data-source.md +96 -0
- package/dist/docs/topics/cubes.dimensions.format.md +199 -0
- package/dist/docs/topics/cubes.dimensions.md +188 -0
- package/dist/docs/topics/cubes.dimensions.primary-key.md +110 -0
- package/dist/docs/topics/cubes.dimensions.sub-query.md +178 -0
- package/dist/docs/topics/cubes.dimensions.time.md +115 -0
- package/dist/docs/topics/cubes.dimensions.types.md +111 -0
- package/dist/docs/topics/cubes.extends.md +153 -0
- package/dist/docs/topics/cubes.hierarchies.md +178 -0
- package/dist/docs/topics/cubes.joins.md +119 -0
- package/dist/docs/topics/cubes.md +121 -0
- package/dist/docs/topics/cubes.measures.calculated.md +103 -0
- package/dist/docs/topics/cubes.measures.drill-members.md +162 -0
- package/dist/docs/topics/cubes.measures.filters.md +90 -0
- package/dist/docs/topics/cubes.measures.format.md +157 -0
- package/dist/docs/topics/cubes.measures.md +166 -0
- package/dist/docs/topics/cubes.measures.rolling.md +123 -0
- package/dist/docs/topics/cubes.measures.types.md +126 -0
- package/dist/docs/topics/cubes.public.md +176 -0
- package/dist/docs/topics/cubes.refresh-key.md +157 -0
- package/dist/docs/topics/cubes.segments.md +125 -0
- package/dist/docs/topics/cubes.sql.md +65 -0
- package/dist/docs/topics/pre-aggregations.md +130 -0
- package/dist/docs/topics/pre-aggregations.rollup.md +166 -0
- package/dist/docs/topics/syntax.context-variables.md +157 -0
- package/dist/docs/topics/syntax.md +137 -0
- package/dist/docs/topics/syntax.references.md +178 -0
- package/dist/docs/topics/views.cubes.md +166 -0
- package/dist/docs/topics/views.folders.md +158 -0
- package/dist/docs/topics/views.includes.md +143 -0
- package/dist/docs/topics/views.md +142 -0
- package/dist/docs/topics/workflow.deploy.md +132 -0
- package/dist/docs/topics/workflow.md +151 -0
- package/dist/docs/topics/workflow.query.md +203 -0
- package/dist/docs/topics/workflow.validate.md +156 -0
- package/dist/templates/claude/rules/bonnard.md +15 -0
- package/dist/templates/claude/settings.json +7 -0
- package/dist/templates/claude/skills/bonnard-cli/SKILL.md +59 -0
- package/dist/templates/claude/skills/bonnard-queries/SKILL.md +68 -0
- package/dist/templates/cursor/rules/bonnard-cli.mdc +47 -0
- package/dist/templates/cursor/rules/bonnard-queries.mdc +49 -0
- package/dist/templates/cursor/rules/bonnard.mdc +20 -0
- package/dist/templates/shared/bonnard.md +81 -0
- package/package.json +13 -8
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# cubes.measures.drill-members
|
|
2
|
+
|
|
3
|
+
> Define which dimensions to show when drilling into a measure.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `drill_members` property specifies which dimensions should be displayed when a user "drills down" into a measure to see the underlying detail records.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
cubes:
|
|
13
|
+
- name: orders
|
|
14
|
+
sql_table: orders
|
|
15
|
+
|
|
16
|
+
measures:
|
|
17
|
+
- name: count
|
|
18
|
+
type: count
|
|
19
|
+
drill_members:
|
|
20
|
+
- id
|
|
21
|
+
- status
|
|
22
|
+
- created_at
|
|
23
|
+
- customer_name
|
|
24
|
+
|
|
25
|
+
- name: total_revenue
|
|
26
|
+
type: sum
|
|
27
|
+
sql: amount
|
|
28
|
+
drill_members:
|
|
29
|
+
- id
|
|
30
|
+
- amount
|
|
31
|
+
- status
|
|
32
|
+
- created_at
|
|
33
|
+
|
|
34
|
+
dimensions:
|
|
35
|
+
- name: id
|
|
36
|
+
type: number
|
|
37
|
+
sql: id
|
|
38
|
+
primary_key: true
|
|
39
|
+
|
|
40
|
+
- name: status
|
|
41
|
+
type: string
|
|
42
|
+
sql: status
|
|
43
|
+
|
|
44
|
+
- name: amount
|
|
45
|
+
type: number
|
|
46
|
+
sql: amount
|
|
47
|
+
|
|
48
|
+
- name: customer_name
|
|
49
|
+
type: string
|
|
50
|
+
sql: customer_name
|
|
51
|
+
|
|
52
|
+
- name: created_at
|
|
53
|
+
type: time
|
|
54
|
+
sql: created_at
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Syntax
|
|
58
|
+
|
|
59
|
+
List dimensions by name:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
measures:
|
|
63
|
+
- name: count
|
|
64
|
+
type: count
|
|
65
|
+
drill_members:
|
|
66
|
+
- id
|
|
67
|
+
- name
|
|
68
|
+
- email
|
|
69
|
+
- created_at
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## How Drill-Down Works
|
|
73
|
+
|
|
74
|
+
1. User sees aggregated measure (e.g., "Orders: 1,234")
|
|
75
|
+
2. User clicks to drill down
|
|
76
|
+
3. BI tool queries the specified `drill_members` dimensions
|
|
77
|
+
4. User sees detail records that make up that aggregate
|
|
78
|
+
|
|
79
|
+
## Cross-Cube Drill Members
|
|
80
|
+
|
|
81
|
+
Reference dimensions from joined cubes:
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
cubes:
|
|
85
|
+
- name: orders
|
|
86
|
+
joins:
|
|
87
|
+
- name: users
|
|
88
|
+
relationship: many_to_one
|
|
89
|
+
sql: "{CUBE}.user_id = {users.id}"
|
|
90
|
+
|
|
91
|
+
measures:
|
|
92
|
+
- name: count
|
|
93
|
+
type: count
|
|
94
|
+
drill_members:
|
|
95
|
+
- id
|
|
96
|
+
- status
|
|
97
|
+
- users.name # From joined cube
|
|
98
|
+
- users.email # From joined cube
|
|
99
|
+
- created_at
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Best Practices
|
|
103
|
+
|
|
104
|
+
### Include Identifying Information
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
drill_members:
|
|
108
|
+
- id # Primary identifier
|
|
109
|
+
- name # Human-readable name
|
|
110
|
+
- created_at # When it happened
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Include Relevant Context
|
|
114
|
+
|
|
115
|
+
```yaml
|
|
116
|
+
# For a revenue measure
|
|
117
|
+
drill_members:
|
|
118
|
+
- order_id
|
|
119
|
+
- product_name
|
|
120
|
+
- amount # The value being summed
|
|
121
|
+
- customer_name
|
|
122
|
+
- order_date
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Keep Lists Focused
|
|
126
|
+
|
|
127
|
+
Don't include every dimension—focus on what's useful for understanding that specific measure:
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
# Good - focused on revenue context
|
|
131
|
+
- name: total_revenue
|
|
132
|
+
drill_members:
|
|
133
|
+
- id
|
|
134
|
+
- amount
|
|
135
|
+
- product
|
|
136
|
+
- customer
|
|
137
|
+
|
|
138
|
+
# Bad - too many unrelated fields
|
|
139
|
+
- name: total_revenue
|
|
140
|
+
drill_members:
|
|
141
|
+
- id
|
|
142
|
+
- amount
|
|
143
|
+
- product
|
|
144
|
+
- customer
|
|
145
|
+
- internal_code
|
|
146
|
+
- debug_flag
|
|
147
|
+
- sync_status
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## BI Tool Support
|
|
151
|
+
|
|
152
|
+
Drill-down support varies by visualization tool. Check your specific tool's documentation for how it handles `drill_members`.
|
|
153
|
+
|
|
154
|
+
## See Also
|
|
155
|
+
|
|
156
|
+
- cubes.measures
|
|
157
|
+
- cubes.dimensions
|
|
158
|
+
- cubes.joins
|
|
159
|
+
|
|
160
|
+
## More Information
|
|
161
|
+
|
|
162
|
+
https://cube.dev/docs/reference/data-model/measures#drill-members
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# cubes.measures.filters
|
|
2
|
+
|
|
3
|
+
> Apply permanent filters to measures for conditional aggregations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `filters` property lets you define measures that only count or aggregate rows matching specific conditions. This creates reusable filtered metrics without requiring query-time filters.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
measures:
|
|
13
|
+
- name: completed_orders
|
|
14
|
+
type: count
|
|
15
|
+
filters:
|
|
16
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
17
|
+
|
|
18
|
+
- name: revenue_this_year
|
|
19
|
+
type: sum
|
|
20
|
+
sql: amount
|
|
21
|
+
filters:
|
|
22
|
+
- sql: "YEAR({CUBE}.created_at) = YEAR(CURRENT_DATE)"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Syntax
|
|
26
|
+
|
|
27
|
+
### Single Filter
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- name: active_users
|
|
31
|
+
type: count_distinct
|
|
32
|
+
sql: user_id
|
|
33
|
+
filters:
|
|
34
|
+
- sql: "{CUBE}.is_active = true"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Multiple Filters (AND logic)
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
- name: completed_paid_orders
|
|
41
|
+
type: count
|
|
42
|
+
filters:
|
|
43
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
44
|
+
- sql: "{CUBE}.payment_status = 'paid'"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Use Cases
|
|
48
|
+
|
|
49
|
+
### Percentage Calculations
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
measures:
|
|
53
|
+
- name: total_orders
|
|
54
|
+
type: count
|
|
55
|
+
|
|
56
|
+
- name: completed_orders
|
|
57
|
+
type: count
|
|
58
|
+
filters:
|
|
59
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
60
|
+
|
|
61
|
+
- name: completion_rate
|
|
62
|
+
type: number
|
|
63
|
+
sql: "100.0 * {completed_orders} / NULLIF({total_orders}, 0)"
|
|
64
|
+
format: percent
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Time-Based Metrics
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
- name: orders_last_30_days
|
|
71
|
+
type: count
|
|
72
|
+
filters:
|
|
73
|
+
- sql: "{CUBE}.created_at >= CURRENT_DATE - INTERVAL '30 days'"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Best Practices
|
|
77
|
+
|
|
78
|
+
1. **Use {CUBE}** to reference the current cube's columns
|
|
79
|
+
2. **Combine with number type** for calculated ratios
|
|
80
|
+
3. **Keep filters simple** — complex logic belongs in the base SQL
|
|
81
|
+
|
|
82
|
+
## See Also
|
|
83
|
+
|
|
84
|
+
- cubes.measures
|
|
85
|
+
- cubes.measures.calculated
|
|
86
|
+
- cubes.segments
|
|
87
|
+
|
|
88
|
+
## More Information
|
|
89
|
+
|
|
90
|
+
https://cube.dev/docs/reference/data-model/measures#filters
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# cubes.measures.format
|
|
2
|
+
|
|
3
|
+
> Specify how measure values should be displayed.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `format` property hints to BI tools how to display measure values. This affects rendering in dashboards and reports.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
measures:
|
|
13
|
+
- name: total_revenue
|
|
14
|
+
type: sum
|
|
15
|
+
sql: amount
|
|
16
|
+
format: currency
|
|
17
|
+
|
|
18
|
+
- name: conversion_rate
|
|
19
|
+
type: number
|
|
20
|
+
sql: "{conversions} / NULLIF({visits}, 0)"
|
|
21
|
+
format: percent
|
|
22
|
+
|
|
23
|
+
- name: order_count
|
|
24
|
+
type: count
|
|
25
|
+
# No format - displays as plain number
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Supported Formats
|
|
29
|
+
|
|
30
|
+
### percent
|
|
31
|
+
|
|
32
|
+
Displays value as a percentage:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
- name: completion_rate
|
|
36
|
+
type: number
|
|
37
|
+
sql: "{completed} / NULLIF({total}, 0)"
|
|
38
|
+
format: percent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Output: `75%` instead of `0.75`
|
|
42
|
+
|
|
43
|
+
### currency
|
|
44
|
+
|
|
45
|
+
Displays value as monetary amount:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
- name: total_revenue
|
|
49
|
+
type: sum
|
|
50
|
+
sql: amount
|
|
51
|
+
format: currency
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Output: `$1,234.56` (formatting depends on BI tool locale)
|
|
55
|
+
|
|
56
|
+
## Usage Notes
|
|
57
|
+
|
|
58
|
+
### Format vs Calculation
|
|
59
|
+
|
|
60
|
+
Format is for display only—it doesn't change the underlying value:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
# Value is 0.75, displayed as 75%
|
|
64
|
+
- name: rate
|
|
65
|
+
type: number
|
|
66
|
+
sql: "{part} / NULLIF({whole}, 0)"
|
|
67
|
+
format: percent
|
|
68
|
+
|
|
69
|
+
# If you want the value to be 75, multiply in SQL
|
|
70
|
+
- name: rate_as_whole_number
|
|
71
|
+
type: number
|
|
72
|
+
sql: "100.0 * {part} / NULLIF({whole}, 0)"
|
|
73
|
+
format: percent # Displays as 7500% - probably not what you want!
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Percentages
|
|
77
|
+
|
|
78
|
+
For percentages, your SQL should return a decimal (0.75 for 75%):
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
# Correct - returns 0.75, displays as 75%
|
|
82
|
+
- name: conversion_rate
|
|
83
|
+
type: number
|
|
84
|
+
sql: "{conversions} / NULLIF({visits}, 0)"
|
|
85
|
+
format: percent
|
|
86
|
+
|
|
87
|
+
# Also correct - explicit multiplication for clarity
|
|
88
|
+
- name: conversion_rate
|
|
89
|
+
type: number
|
|
90
|
+
sql: "1.0 * {conversions} / NULLIF({visits}, 0)"
|
|
91
|
+
format: percent
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Currency
|
|
95
|
+
|
|
96
|
+
For currency, return the raw numeric value:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
# Correct - returns 1234.56, displays as $1,234.56
|
|
100
|
+
- name: revenue
|
|
101
|
+
type: sum
|
|
102
|
+
sql: amount
|
|
103
|
+
format: currency
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Common Patterns
|
|
107
|
+
|
|
108
|
+
### Financial Measures
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
measures:
|
|
112
|
+
- name: revenue
|
|
113
|
+
type: sum
|
|
114
|
+
sql: amount
|
|
115
|
+
format: currency
|
|
116
|
+
|
|
117
|
+
- name: cost
|
|
118
|
+
type: sum
|
|
119
|
+
sql: cost
|
|
120
|
+
format: currency
|
|
121
|
+
|
|
122
|
+
- name: profit_margin
|
|
123
|
+
type: number
|
|
124
|
+
sql: "({revenue} - {cost}) / NULLIF({revenue}, 0)"
|
|
125
|
+
format: percent
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Conversion Metrics
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
measures:
|
|
132
|
+
- name: visits
|
|
133
|
+
type: count_distinct
|
|
134
|
+
sql: session_id
|
|
135
|
+
|
|
136
|
+
- name: signups
|
|
137
|
+
type: count
|
|
138
|
+
|
|
139
|
+
- name: signup_rate
|
|
140
|
+
type: number
|
|
141
|
+
sql: "{signups} / NULLIF({visits}, 0)"
|
|
142
|
+
format: percent
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## BI Tool Support
|
|
146
|
+
|
|
147
|
+
Format support varies by visualization tool. Most tools recognize `percent` and `currency`, but rendering specifics (decimal places, currency symbol) depend on the tool's configuration.
|
|
148
|
+
|
|
149
|
+
## See Also
|
|
150
|
+
|
|
151
|
+
- cubes.measures
|
|
152
|
+
- cubes.measures.types
|
|
153
|
+
- cubes.dimensions.format
|
|
154
|
+
|
|
155
|
+
## More Information
|
|
156
|
+
|
|
157
|
+
https://cube.dev/docs/reference/data-model/types-and-formats#format
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# cubes.measures
|
|
2
|
+
|
|
3
|
+
> Define metrics and aggregations for analytical queries.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Measures are the quantitative values in your data model — counts, sums, averages, and other aggregations. They answer questions like "how many?", "how much?", and "what's the average?".
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
measures:
|
|
13
|
+
- name: count
|
|
14
|
+
type: count
|
|
15
|
+
description: Total number of orders
|
|
16
|
+
|
|
17
|
+
- name: total_revenue
|
|
18
|
+
type: sum
|
|
19
|
+
sql: amount
|
|
20
|
+
description: Sum of order amounts in dollars
|
|
21
|
+
|
|
22
|
+
- name: average_order_value
|
|
23
|
+
type: number
|
|
24
|
+
sql: "{total_revenue} / NULLIF({count}, 0)"
|
|
25
|
+
description: Average revenue per order
|
|
26
|
+
|
|
27
|
+
- name: completed_orders
|
|
28
|
+
type: count
|
|
29
|
+
filters:
|
|
30
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
31
|
+
description: Orders with status completed
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Required Properties
|
|
35
|
+
|
|
36
|
+
| Property | Description |
|
|
37
|
+
|----------|-------------|
|
|
38
|
+
| `name` | Unique identifier in snake_case |
|
|
39
|
+
| `type` | Aggregation type (count, sum, avg, etc.) |
|
|
40
|
+
|
|
41
|
+
## Optional Properties
|
|
42
|
+
|
|
43
|
+
| Property | Description |
|
|
44
|
+
|----------|-------------|
|
|
45
|
+
| `sql` | SQL expression (required for most types) |
|
|
46
|
+
| `filters` | Conditions for filtered aggregations |
|
|
47
|
+
| `title` | Human-readable display name |
|
|
48
|
+
| `description` | Documentation for consumers |
|
|
49
|
+
| `format` | Output format (percent, currency, etc.) |
|
|
50
|
+
| `public` | Whether exposed in API (default: true) |
|
|
51
|
+
| `rolling_window` | Rolling aggregation settings |
|
|
52
|
+
|
|
53
|
+
## Measure Types
|
|
54
|
+
|
|
55
|
+
### Aggregation Types
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
# Count rows
|
|
59
|
+
- name: count
|
|
60
|
+
type: count
|
|
61
|
+
|
|
62
|
+
# Count distinct values
|
|
63
|
+
- name: unique_users
|
|
64
|
+
type: count_distinct
|
|
65
|
+
sql: user_id
|
|
66
|
+
|
|
67
|
+
# Sum values
|
|
68
|
+
- name: total_revenue
|
|
69
|
+
type: sum
|
|
70
|
+
sql: amount
|
|
71
|
+
|
|
72
|
+
# Average values
|
|
73
|
+
- name: average_price
|
|
74
|
+
type: avg
|
|
75
|
+
sql: price
|
|
76
|
+
|
|
77
|
+
# Min/Max values
|
|
78
|
+
- name: first_order
|
|
79
|
+
type: min
|
|
80
|
+
sql: created_at
|
|
81
|
+
|
|
82
|
+
- name: last_order
|
|
83
|
+
type: max
|
|
84
|
+
sql: created_at
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Calculated Types
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
# Calculated number (from other measures)
|
|
91
|
+
- name: average_order_value
|
|
92
|
+
type: number
|
|
93
|
+
sql: "{total_revenue} / NULLIF({count}, 0)"
|
|
94
|
+
|
|
95
|
+
# Boolean result
|
|
96
|
+
- name: has_orders
|
|
97
|
+
type: boolean
|
|
98
|
+
sql: "{count} > 0"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Filtered Measures
|
|
102
|
+
|
|
103
|
+
Add conditions to only count/sum matching rows:
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
- name: completed_orders
|
|
107
|
+
type: count
|
|
108
|
+
filters:
|
|
109
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
110
|
+
|
|
111
|
+
- name: revenue_this_year
|
|
112
|
+
type: sum
|
|
113
|
+
sql: amount
|
|
114
|
+
filters:
|
|
115
|
+
- sql: "YEAR({CUBE}.created_at) = YEAR(CURRENT_DATE)"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Calculated Measures
|
|
119
|
+
|
|
120
|
+
Reference other measures to build derived metrics:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
- name: total_orders
|
|
124
|
+
type: count
|
|
125
|
+
|
|
126
|
+
- name: completed_orders
|
|
127
|
+
type: count
|
|
128
|
+
filters:
|
|
129
|
+
- sql: "{CUBE}.status = 'completed'"
|
|
130
|
+
|
|
131
|
+
- name: completion_rate
|
|
132
|
+
type: number
|
|
133
|
+
sql: "100.0 * {completed_orders} / NULLIF({total_orders}, 0)"
|
|
134
|
+
format: percent
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Rolling Windows
|
|
138
|
+
|
|
139
|
+
Calculate metrics over time windows:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
- name: rolling_7_day_revenue
|
|
143
|
+
type: sum
|
|
144
|
+
sql: amount
|
|
145
|
+
rolling_window:
|
|
146
|
+
trailing: 7 day
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Best Practices
|
|
150
|
+
|
|
151
|
+
1. **Start with count** — every cube should have a basic count
|
|
152
|
+
2. **Use descriptive names** — `total_revenue` not `sum1`
|
|
153
|
+
3. **Handle division by zero** — always use `NULLIF(x, 0)`
|
|
154
|
+
4. **Add formats** — help consumers interpret values
|
|
155
|
+
5. **Document complex measures** — explain business logic
|
|
156
|
+
|
|
157
|
+
## See Also
|
|
158
|
+
|
|
159
|
+
- cubes.measures.types
|
|
160
|
+
- cubes.measures.filters
|
|
161
|
+
- cubes.measures.calculated
|
|
162
|
+
- cubes.measures.rolling
|
|
163
|
+
|
|
164
|
+
## More Information
|
|
165
|
+
|
|
166
|
+
https://cube.dev/docs/reference/data-model/measures
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# cubes.measures.rolling
|
|
2
|
+
|
|
3
|
+
> Calculate rolling window aggregations (7-day average, 30-day sum, etc).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Rolling window measures aggregate data over a sliding time period. Use `rolling_window` to define moving averages, cumulative totals, and time-based comparisons.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
measures:
|
|
13
|
+
- name: rolling_7_day_orders
|
|
14
|
+
type: count
|
|
15
|
+
rolling_window:
|
|
16
|
+
trailing: 7 day
|
|
17
|
+
offset: start
|
|
18
|
+
|
|
19
|
+
- name: rolling_30_day_revenue
|
|
20
|
+
type: sum
|
|
21
|
+
sql: amount
|
|
22
|
+
rolling_window:
|
|
23
|
+
trailing: 30 day
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Syntax
|
|
27
|
+
|
|
28
|
+
### rolling_window Properties
|
|
29
|
+
|
|
30
|
+
| Property | Description |
|
|
31
|
+
|----------|-------------|
|
|
32
|
+
| `trailing` | Time period to look back (e.g., `7 day`, `1 month`) |
|
|
33
|
+
| `leading` | Time period to look forward (rare) |
|
|
34
|
+
| `offset` | `start` or `end` — which end of the window to align |
|
|
35
|
+
|
|
36
|
+
### Trailing Window
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- name: rolling_7_day_avg
|
|
40
|
+
type: avg
|
|
41
|
+
sql: amount
|
|
42
|
+
rolling_window:
|
|
43
|
+
trailing: 7 day
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Cumulative (Running Total)
|
|
47
|
+
|
|
48
|
+
Use `unbounded` for cumulative calculations:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
- name: cumulative_revenue
|
|
52
|
+
type: sum
|
|
53
|
+
sql: amount
|
|
54
|
+
rolling_window:
|
|
55
|
+
trailing: unbounded
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Offset Options
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
# Window ends at current row (default)
|
|
62
|
+
rolling_window:
|
|
63
|
+
trailing: 7 day
|
|
64
|
+
offset: end
|
|
65
|
+
|
|
66
|
+
# Window starts at current row
|
|
67
|
+
rolling_window:
|
|
68
|
+
trailing: 7 day
|
|
69
|
+
offset: start
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Common Patterns
|
|
73
|
+
|
|
74
|
+
### 7-Day Moving Average
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
- name: daily_orders
|
|
78
|
+
type: count
|
|
79
|
+
|
|
80
|
+
- name: rolling_7_day_avg_orders
|
|
81
|
+
type: avg
|
|
82
|
+
sql: "{daily_orders}"
|
|
83
|
+
rolling_window:
|
|
84
|
+
trailing: 7 day
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Month-to-Date
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
- name: mtd_revenue
|
|
91
|
+
type: sum
|
|
92
|
+
sql: amount
|
|
93
|
+
rolling_window:
|
|
94
|
+
trailing: 1 month
|
|
95
|
+
offset: start
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Year-to-Date
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
- name: ytd_revenue
|
|
102
|
+
type: sum
|
|
103
|
+
sql: amount
|
|
104
|
+
rolling_window:
|
|
105
|
+
trailing: 1 year
|
|
106
|
+
offset: start
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Requirements
|
|
110
|
+
|
|
111
|
+
- Rolling window measures require a time dimension in the query
|
|
112
|
+
- Works best with pre-aggregations for performance
|
|
113
|
+
|
|
114
|
+
## See Also
|
|
115
|
+
|
|
116
|
+
- cubes.measures
|
|
117
|
+
- cubes.measures.calculated
|
|
118
|
+
- cubes.dimensions.time
|
|
119
|
+
- pre-aggregations
|
|
120
|
+
|
|
121
|
+
## More Information
|
|
122
|
+
|
|
123
|
+
https://cube.dev/docs/reference/data-model/measures#rolling-window
|