Skip to main content
Timeplus Proton supports standard SQL SELECT queries with extensions for streaming semantics.

Basic SELECT Queries

Streaming Select

Query streams in real-time mode:
-- Stream all events as they arrive
SELECT * FROM events;

-- Select specific columns
SELECT event_id, user_id, event_type 
FROM events;
Streaming queries:
  • Start from the latest data by default
  • Run continuously until cancelled
  • Return results as events arrive

Historical Select

Query historical data using the table() function:
-- Query all historical data
SELECT * FROM table(events);

-- Query with ordering
SELECT * FROM table(events)
ORDER BY event_time DESC
LIMIT 100;

Filtering with WHERE

Basic Filtering

-- Filter by column value
SELECT * FROM transactions
WHERE amount > 1000;

-- Multiple conditions
SELECT * FROM events
WHERE event_type = 'purchase' 
  AND user_id > 100;

-- String matching
SELECT * FROM logs
WHERE message LIKE '%error%';

Time-based Filtering

Filter by event time using _tp_time:
-- Events from last hour
SELECT * FROM events
WHERE _tp_time > now() - INTERVAL 1 HOUR;

-- Specific date range (historical)
SELECT * FROM table(events)
WHERE _tp_time >= '2024-01-01'
  AND _tp_time < '2024-02-01';

-- Events from today
SELECT * FROM table(events)
WHERE to_date(_tp_time) = today();

Projection and Transformation

Column Selection

-- Select specific columns
SELECT user_id, event_type, event_time
FROM events;

-- Column aliases
SELECT 
  user_id as uid,
  event_type as type,
  event_time as ts
FROM events;

-- Exclude columns with EXCEPT
SELECT * EXCEPT (_tp_time, _tp_sn)
FROM events;

Column Transformations

-- Apply functions
SELECT 
  upper(event_type) as event_type,
  amount * 1.1 as amount_with_tax,
  to_string(event_time) as time_str
FROM events;

-- Conditional expressions
SELECT 
  order_id,
  CASE 
    WHEN amount < 100 THEN 'small'
    WHEN amount < 1000 THEN 'medium'
    ELSE 'large'
  END as order_size
FROM orders;

Query Settings

Controlling Start Position

Control where streaming queries begin:
-- Start from earliest available data
SELECT * FROM events
SETTINGS seek_to = 'earliest';

-- Start from latest (default)
SELECT * FROM events
SETTINGS seek_to = 'latest';

-- Specify timestamp
SELECT * FROM events
SETTINGS seek_to = '2024-01-01 00:00:00';

Performance Settings

-- Limit parallel processing
SELECT * FROM events
SETTINGS max_threads = 4;

-- Memory limits
SELECT * FROM events
SETTINGS max_memory_usage = 10000000000;  -- 10GB

Streaming vs Historical Queries

Streaming Query Characteristics

-- This runs continuously
SELECT device_id, temperature 
FROM sensor_readings
WHERE temperature > 80;
Streaming mode:
  • Unbounded data processing
  • Real-time results
  • No automatic termination
  • Lower latency

Historical Query Characteristics

-- This processes bounded data and terminates
SELECT device_id, avg(temperature) as avg_temp
FROM table(sensor_readings)
GROUP BY device_id
ORDER BY avg_temp DESC;
Historical mode:
  • Bounded dataset
  • Complete result set
  • Automatic termination
  • Supports ORDER BY, LIMIT globally

Subqueries

Historical Subqueries

-- Subquery for filtering
SELECT * FROM events
WHERE user_id IN (
  SELECT user_id FROM table(premium_users)
);

-- Derived tables
SELECT 
  date,
  avg(daily_total) as avg_daily
FROM (
  SELECT 
    to_date(_tp_time) as date,
    sum(amount) as daily_total
  FROM table(transactions)
  GROUP BY date
)
GROUP BY date;

WITH Common Table Expressions

WITH high_value_users AS (
  SELECT user_id, sum(amount) as total
  FROM table(transactions)
  WHERE _tp_time > now() - INTERVAL 30 DAY
  GROUP BY user_id
  HAVING total > 10000
)
SELECT 
  e.event_type,
  count() as event_count
FROM events e
INNER JOIN high_value_users h ON e.user_id = h.user_id
GROUP BY e.event_type;

LIMIT and Sampling

LIMIT in Historical Queries

-- Limit results in historical query
SELECT * FROM table(events)
ORDER BY _tp_time DESC
LIMIT 100;

LIMIT in Streaming Queries

-- Process first 1000 events then stop
SELECT * FROM events
LIMIT 1000;

-- Limit per time window
SELECT count(*) as cnt
FROM events
LIMIT 5 EMIT PERIODIC INTERVAL 1 SECOND;

DISTINCT

Get unique values:
-- Distinct event types (historical)
SELECT DISTINCT event_type 
FROM table(events);

-- Count distinct users
SELECT count(DISTINCT user_id) as unique_users
FROM table(events)
WHERE to_date(_tp_time) = today();

Working with JSON Data

Extract JSON Fields

-- Parse JSON string column
SELECT 
  event_id,
  json_extract_string(metadata, 'user_agent') as user_agent,
  json_extract_int(metadata, 'session_duration') as duration
FROM events;

-- JSON path expressions
SELECT 
  json_extract(payload, '$.user.id') as user_id,
  json_extract(payload, '$.items[0].price') as first_item_price
FROM orders;

Complete Query Examples

Real-time Monitoring

-- Monitor high-value transactions in real-time
SELECT 
  transaction_id,
  user_id,
  amount,
  currency,
  created_at
FROM transactions
WHERE amount > 10000
  AND status = 'completed';

Historical Analysis

-- Analyze yesterday's user activity
SELECT 
  event_type,
  count() as event_count,
  count(DISTINCT user_id) as unique_users,
  avg(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) as purchase_rate
FROM table(events)
WHERE to_date(_tp_time) = today() - 1
GROUP BY event_type
ORDER BY event_count DESC;

Filtered Streaming

-- Stream only anomalous sensor readings
SELECT 
  sensor_id,
  temperature,
  humidity,
  reading_time,
  CASE
    WHEN temperature > 100 THEN 'temp_high'
    WHEN temperature < -20 THEN 'temp_low'
    WHEN humidity > 95 THEN 'humidity_high'
    ELSE 'normal'
  END as alert_type
FROM iot_sensors
WHERE temperature > 100 
   OR temperature < -20 
   OR humidity > 95
SETTINGS seek_to = 'earliest';

Time Window Queries

-- Get latest value per device in last 5 minutes
SELECT 
  device_id,
  any_last(temperature) as latest_temp,
  max(_tp_time) as last_reading
FROM table(sensor_readings)
WHERE _tp_time > now() - INTERVAL 5 MINUTE
GROUP BY device_id;

Best Practices

Filter data as early as possible to reduce processing:
-- Good: Filter before processing
SELECT user_id, count() 
FROM events 
WHERE event_type = 'purchase'
GROUP BY user_id;

-- Less efficient: Filter after aggregation
SELECT user_id, cnt FROM (
  SELECT user_id, event_type, count() as cnt
  FROM events
  GROUP BY user_id, event_type
) WHERE event_type = 'purchase';
  • Use streaming queries for real-time monitoring and alerts
  • Use table() for analytical queries and reporting
  • Consider data volume when choosing mode
Select only needed columns to reduce network and memory overhead:
-- Good: Select specific columns
SELECT user_id, event_type FROM events;

-- Avoid: SELECT * when not needed
SELECT * FROM events;  -- Transfers all columns
When exploring data, use LIMIT to avoid overwhelming results:
SELECT * FROM events LIMIT 10;

Next Steps

Writing Data

Learn how to insert data into streams

Aggregations

Perform streaming aggregations

Time Windows

Use time-based windows

Joins

Join multiple streams