Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
413 changes: 413 additions & 0 deletions documentation/query/operators/exchange-calendars.md

Large diffs are not rendered by default.

100 changes: 73 additions & 27 deletions documentation/query/operators/tick.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,62 @@ sidebar_label: TICK intervals
description:
TICK (Temporal Interval Calendar Kit) - a powerful syntax for expressing
complex temporal intervals in QuestDB queries.
keywords:
- time filter
- date range
- time range
- business days
- trading hours
- workday
- $today
- $now
- timestamp interval
- WHERE IN
---

import { EnterpriseNote } from "@site/src/components/EnterpriseNote"

TICK (Temporal Interval Calendar Kit) is a syntax for expressing complex
temporal intervals in a single string. Use it with the `IN` operator to query
multiple time ranges, schedules, and patterns efficiently.

```questdb-sql
-- NYSE trading hours on workdays for January
SELECT * FROM trades
WHERE ts IN '2024-01-[01..31]T09:30@America/New_York#workday;6h30m';
WHERE ts IN '2025-01-[02..8,10..19,21..31]T09:30@America/New_York#workday;6h30m';
```

This single expression generates interval scans for every weekday except
holidays in January, each starting at 9:30 AM New York time and lasting 6 hours
30 minutes.

<EnterpriseNote>
With [exchange calendars](/docs/query/operators/exchange-calendars/), TICK
directly understands exchange schedules including holidays, early closes, and
lunch breaks. Here's an expression equivalent to the one above (XNYS is the
ISO 10383 MIC code of NYSE):

```questdb-sql
-- NYSE trading hours for January, holidays excluded automatically
SELECT * FROM trades
WHERE ts IN '2025-01-[01..31]#XNYS';
```

This single expression generates interval scans for every weekday in January,
each starting at 9:30 AM New York time and lasting 6 hours 30 minutes.
</EnterpriseNote>

:::tip Key Points

- TICK = declarative syntax for complex time intervals in `WHERE ts IN '...'`
- **Syntax order:** `date [T time] @timezone #dayFilter ;duration`
- Each generated interval uses optimized [interval scan](/docs/concepts/deep-dive/interval-scan/) (binary search)
- Each generated interval uses optimized
[interval scan](/docs/concepts/deep-dive/interval-scan/) (binary search)
- Use `[a,b,c]` for values, `[a..b]` for ranges, `#workday` for day filters
- Overlapping intervals are automatically merged
:::

## Grammar summary

```
```text
TICK_EXPR = DATE_PART [TIME] [TIMEZONE] [FILTER] [DURATION]

DATE_PART = literal_date -- '2024-01-15'
Expand All @@ -46,6 +76,7 @@ TIMEZONE = '@' iana_name -- '@America/New_York'

FILTER = '#workday' | '#weekend' -- business day filters
| '#' day_list -- '#Mon,Wed,Fri'
| '#' exchange_code -- '#XNYS' (exchange calendar, Enterprise)

DURATION = ';' duration_value -- ';6h30m'

Expand All @@ -71,9 +102,14 @@ unit = 'y' | 'M' | 'w' | 'd' | 'bd' | 'h' | 'm' | 's' | 'T' | 'u' | 'n'
-- 'bd' (business days) valid only in date arithmetic, not duration
```

The `exchange_code` filter uses an ISO 10383 MIC code (e.g., `#XNYS`) to apply
real exchange trading schedules. See
[exchange calendars](/docs/query/operators/exchange-calendars/) for details.

## Why TICK

Traditional approaches to complex time queries require:

- Multiple `UNION ALL` statements
- Application-side date generation
- Complex `BETWEEN` logic with many `OR` clauses
Expand All @@ -82,13 +118,15 @@ TICK replaces all of these with a declarative syntax that generates multiple
optimized interval scans from a single expression.

**Use TICK when:**

- Querying relative time windows (`$now - 1h..$now`, `$today`)
- Building rolling windows with business day calculations
- Working with schedules (workdays, weekends, specific days)
- Needing timezone-aware time windows with DST handling
- Querying multiple non-contiguous dates or time windows

**Use simple `IN` or `BETWEEN` when:**

- Single continuous time range with absolute dates (`WHERE ts IN '2024-01-15'`)
- Simple date/time literals without patterns or variables

Expand Down Expand Up @@ -123,7 +161,7 @@ WHERE ts IN '2024-01-15T09:30@America/New_York;6h30m'

Components must appear in this order:

```
```text
date [T time] @ timezone # dayFilter ; duration
│ │ │ │ │
│ │ │ │ └─ interval length (e.g., ;6h30m)
Expand All @@ -136,7 +174,7 @@ date [T time] @ timezone # dayFilter ; duration
**Examples showing the order:**

| Expression | Components used |
|------------|-----------------|
| ---------- | --------------- |
| `'2024-01-15'` | date only |
| `'2024-01-15T09:30'` | date + time |
| `'2024-01-15T09:30@UTC'` | date + time + timezone |
Expand All @@ -147,7 +185,7 @@ date [T time] @ timezone # dayFilter ; duration
## Quick reference

| Feature | Syntax | Example |
|---------|--------|---------|
| ------- | ------ | ------- |
| Bracket expansion | `[a,b,c]` | `'2024-01-[10,15,20]'` |
| Range expansion | `[a..b]` | `'2024-01-[10..15]'` |
| Date list | `[date1,date2]` | `'[2024-01-15,2024-03-20]'` |
Expand Down Expand Up @@ -224,18 +262,21 @@ WHERE ts IN '[$today, $yesterday, 2024-01-15]'
Use dynamic date references that resolve at query time:

| Variable | Description | Interval type | Example value (Jan 22, 2026 at 14:35:22) |
|----------|-------------|---------------|------------------------------------------|
| -------- | ----------- | ------------- | ---------------------------------------- |
| `$today` | Current day | Full day | `2026-01-22T00:00:00` to `2026-01-22T23:59:59.999999` |
| `$yesterday` | Previous day | Full day | `2026-01-21T00:00:00` to `2026-01-21T23:59:59.999999` |
| `$tomorrow` | Next day | Full day | `2026-01-23T00:00:00` to `2026-01-23T23:59:59.999999` |
| `$now` | Current timestamp | Point-in-time | `2026-01-22T14:35:22.123456` (exact moment) |

:::info Interval vs point-in-time

- **`$today`**, **`$yesterday`**, **`$tomorrow`** produce **full day intervals** (midnight to midnight)
- **`$now`** produces a **point-in-time** (exact moment with microsecond precision)
- **`$today`**, **`$yesterday`**, **`$tomorrow`** produce **full day intervals**
(midnight to midnight)
- **`$now`** produces a **point-in-time** (exact moment with microsecond
precision)

Without a duration suffix, `$now` matches only the exact microsecond. Add a duration or use a range to create a useful window:
Without a duration suffix, `$now` matches only the exact microsecond. Add a
duration or use a range to create a useful window:

```questdb-sql
-- Point-in-time: matches only the exact microsecond (rarely useful alone)
Expand All @@ -254,8 +295,8 @@ Variables are case-insensitive: `$TODAY`, `$Today`, and `$today` are equivalent.

### Date arithmetic

Add or subtract time from date variables using any [time unit](#time-units).
All units except `bd` (business days) work in both duration and arithmetic contexts.
Add or subtract time from date variables using any [time unit](#time-units). All
units except `bd` (business days) work in both duration and arithmetic contexts.

```questdb-sql
-- Calendar day arithmetic
Expand Down Expand Up @@ -307,7 +348,8 @@ Generate multiple intervals from start to end:

:::note Ranges vs durations

**Ranges** (`$start..$end`) create a single continuous interval from start to end:
**Ranges** (`$start..$end`) create a single continuous interval from start to
end:

```questdb-sql
-- Single interval: from 2 hours ago until now
Expand All @@ -330,6 +372,7 @@ For multiple discrete intervals, use a list with duration:
-- Three separate 1-hour intervals
'[$now - 3h, $now - 2h, $now - 1h];1h'
```

:::

### Mixed date lists
Expand Down Expand Up @@ -377,7 +420,7 @@ SELECT * FROM trades WHERE ts IN '2024-[01,06]-[10,15]';
Brackets work in any numeric field:

| Field | Example | Result |
|-------|---------|--------|
| ----- | ------- | ------ |
| Month | `'2024-[01,06]-15'` | Jan 15, Jun 15 |
| Day | `'2024-01-[10,15]'` | 10th, 15th |
| Hour | `'2024-01-10T[09,14]:30'` | 09:30, 14:30 |
Expand Down Expand Up @@ -423,7 +466,7 @@ SELECT * FROM metrics WHERE ts IN '2024-01-15T[08:00,12:00,18:00];30m';
The presence of `:` inside the bracket determines the mode:

| Syntax | Mode | Expands to |
|--------|------|------------|
| ------ | ---- | ---------- |
| `T[09,14]:30` | Numeric expansion (hour field) | 09:30 and 14:30 |
| `T[09:00,14:30]` | Time list (complete times) | 09:00 and 14:30 |

Expand All @@ -450,7 +493,7 @@ SELECT * FROM trades WHERE ts IN '2024-01-15T09:30@UTC';
### Supported timezone formats

| Format | Example |
|--------|---------|
| ------ | ------- |
| IANA name | `@America/New_York`, `@Europe/London` |
| Offset | `@+03:00`, `@-05:00` |
| Compact offset | `@+0300`, `@-0500` |
Expand Down Expand Up @@ -489,7 +532,7 @@ SELECT * FROM attendance WHERE ts IN '2024-01-[01..31]#Mon,Wed,Fri';
### Available filters

| Filter | Days included |
|--------|---------------|
| ------ | ------------- |
| `#workday` or `#wd` | Monday - Friday |
| `#weekend` | Saturday, Sunday |
| `#Mon`, `#Tue`, etc. | Specific day |
Expand Down Expand Up @@ -526,7 +569,7 @@ SELECT * FROM hft_data WHERE ts IN '2024-01-15T09:30:00;1s500T';
### Time units

| Unit | Name | Description | Duration | Arithmetic |
|------|------|-------------|:--------:|:----------:|
| ---- | ---- | ----------- | :------: | :--------: |
| `y` | Years | Calendar years (handles leap years) | Yes | Yes |
| `M` | Months | Calendar months (handles varying lengths) | Yes | Yes |
| `w` | Weeks | 7 days | Yes | Yes |
Expand All @@ -539,8 +582,8 @@ SELECT * FROM hft_data WHERE ts IN '2024-01-15T09:30:00;1s500T';
| `u` | Microseconds | 1,000 nanoseconds | Yes | Yes |
| `n` | Nanoseconds | Base unit | Yes | Yes |

Units are case-sensitive: `M` = months, `m` = minutes, `T` = milliseconds.
The `d` unit also accepts uppercase `D` for backward compatibility.
Units are case-sensitive: `M` = months, `m` = minutes, `T` = milliseconds. The
`d` unit also accepts uppercase `D` for backward compatibility.

### Multi-unit durations

Expand Down Expand Up @@ -588,7 +631,7 @@ SELECT * FROM trades WHERE ts IN '2024-W[01..04]-[1,5]';
### Day-of-week values

| Value | Day |
|-------|-----|
| ----- | --- |
| 1 | Monday |
| 2 | Tuesday |
| 3 | Wednesday |
Expand Down Expand Up @@ -694,7 +737,7 @@ WHERE ts IN '2024-01-[15,16,17]T09:00;1h';
## Error messages

| Error | Cause |
|-------|-------|
| ----- | ----- |
| `Unclosed '[' in interval` | Missing closing bracket |
| `Empty bracket expansion` | Nothing inside brackets |
| `Range must be ascending: 15..10` | End before start in range |
Expand All @@ -704,7 +747,10 @@ WHERE ts IN '2024-01-[15,16,17]T09:00;1h';

## See also

- [Designated timestamp](/docs/concepts/designated-timestamp/) — Required for interval scan optimization
- [Interval scan](/docs/concepts/deep-dive/interval-scan/) — How QuestDB optimizes time queries
- [Designated timestamp](/docs/concepts/designated-timestamp/) — Required for
interval scan optimization
- [Interval scan](/docs/concepts/deep-dive/interval-scan/) — How QuestDB
optimizes time queries
- [WHERE clause](/docs/query/sql/where/) — Full WHERE syntax reference
- [Date/time operators](/docs/query/operators/date-time/) — Additional timestamp operators
- [Date/time operators](/docs/query/operators/date-time/) — Additional timestamp
operators
13 changes: 6 additions & 7 deletions documentation/query/sql/acl/add-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ description:
Enterprise."
---

import { EnterpriseNote } from "@site/src/components/EnterpriseNote"

<EnterpriseNote>
RBAC provides fine-grained database permissions management.
</EnterpriseNote>

To add user to one or more groups in the database, the `ADD USER` keywords are
used.

For full documentation of the Access Control List and Role-based Access Control,
see the [RBAC operations](/docs/security/rbac) page.

:::note

Role-based Access Control (RBAC) operations are only available in QuestDB
Enterprise.

:::

---

## Syntax
Expand Down
13 changes: 6 additions & 7 deletions documentation/query/sql/acl/alter-service-account.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ description:
in QuestDB Enterprise."
---

import { EnterpriseNote } from "@site/src/components/EnterpriseNote"

<EnterpriseNote>
RBAC provides fine-grained database permissions management.
</EnterpriseNote>

`ALTER SERVICE ACCOUNT` modifies service account settings.

For full documentation of the Access Control List and Role-based Access Control,
see the [RBAC operations](/docs/security/rbac) page.

:::note

Role-based Access Control (RBAC) operations are only available in QuestDB
Enterprise.

:::

---

## Syntax
Expand Down
17 changes: 7 additions & 10 deletions documentation/query/sql/acl/alter-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ description:
Enterprise."
---

For full documentation of the Access Control List and Role-based Access Control,
see the [RBAC operations](/docs/security/rbac) page.

:::note

Role-based Access Control (RBAC) operations are only available in QuestDB
Enterprise.
import { EnterpriseNote } from "@site/src/components/EnterpriseNote"

:::

---
<EnterpriseNote>
RBAC provides fine-grained database permissions management.
</EnterpriseNote>

`ALTER USER` modifies user settings.

For full documentation of the Access Control List and Role-based Access Control,
see the [RBAC operations](/docs/security/rbac) page.

## Syntax

![Flow chart showing the syntax of the ALTER USER keyword](/images/docs/diagrams/alterUser.svg)
Expand Down
13 changes: 6 additions & 7 deletions documentation/query/sql/acl/assume-service-account.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ description:
in QuestDB Enterprise"
---

import { EnterpriseNote } from "@site/src/components/EnterpriseNote"

<EnterpriseNote>
RBAC provides fine-grained database permissions management.
</EnterpriseNote>

`ASSUME SERVICE ACCOUNT` switches current user to a service account, basically
replacing its current access list with the service account's access list.

For full documentation of the Access Control List and Role-based Access Control,
see the [RBAC operations](/docs/security/rbac) page.

:::note

Role-based Access Control (RBAC) operations are only available in QuestDB
Enterprise.

:::

---

## Syntax
Expand Down
Loading