KDB knowledge

LATEST ON

Keep only the newest row of each symbol (or of each group of columns).

LATEST ON keeps one row per group: the row with the newest time. The usual use is "the last price of every symbol" from a table of live price snapshots.

Example: Live market: the last snapshot of every symbol (sample data: sample)

SELECT symbol, ltp, point_change, pct_change, timestamp
FROM live_data
LATEST ON timestamp PARTITION BY symbol
ORDER BY pct_change DESC;

Result:

symbol (SYMBOL)ltp (DOUBLE)point_change (DOUBLE)pct_change (DOUBLE)timestamp (TIMESTAMP)
CITY527.113.92.712026-09-10T09:14:00.000Z
TELCO897.716.71.92026-09-10T09:14:00.000Z
COAST401.92.80.72026-09-10T09:14:00.000Z
VOLT184-1.6-0.862026-09-10T09:14:00.000Z

(4 rows)

LATEST ON

Syntax:

SELECT ...
FROM table
[WHERE condition]
LATEST ON time_column PARTITION BY column [, column ...]
[GROUP BY ...] [HAVING ...]
[ORDER BY ...] [LIMIT n]

For each different value of the PARTITION BY columns, keeps only the row with the biggest time_column. All other rows are dropped before the SELECT list is computed.

PartTypeMeaning
time_columnTIMESTAMP or DATE column"newest" means the biggest value of this column
column, ...column namesthe groups: one row is kept per different value (or per different combination of values)

Example: The newest daily candle of every symbol (sample data: sample)

SELECT time, symbol, close, volume
FROM ochl_day
LATEST ON time PARTITION BY symbol;

Result:

time (TIMESTAMP)symbol (SYMBOL)close (DOUBLE)volume (DOUBLE)
2026-09-10T00:00:00.000ZCITY504.9183040
2026-09-10T00:00:00.000ZCOAST376.1186200
2026-09-10T00:00:00.000ZVOLT191.241470

(3 rows)

Example: Two columns: the last trade of each broker in each symbol (sample data: sample)

SELECT buyer, symbol, date, transaction_id, quantity, rate
FROM trade_log
LATEST ON date PARTITION BY buyer, symbol
ORDER BY buyer, symbol
LIMIT 6;

Result:

buyer (INT)symbol (SYMBOL)date (TIMESTAMP)transaction_id (LONG)quantity (LONG)rate (DOUBLE)
1CITY2026-09-10T00:00:00.000Z100024100514.5
1COAST2026-09-10T00:00:00.000Z100026200400
1TELCO2026-09-10T00:00:00.000Z10002150878
1VOLT2026-09-10T00:00:00.000Z100020100187
34CITY2026-09-09T00:00:00.000Z100004500514.5
34COAST2026-09-10T00:00:00.000Z10000950400

(6 rows)

Example: App users: the last person who logged in from each city (sample data: query-app)

SELECT city, username, last_login
FROM app_users
LATEST ON last_login PARTITION BY city
ORDER BY last_login DESC;

Result:

city (STRING)username (STRING)last_login (TIMESTAMP)
Lalitpurbikash2026-09-11T04:20:00.000Z
Dharangita2026-09-11T00:45:00.000Z
Kathmanduram2026-09-10T14:30:00.000Z
Pokharasuman2026-09-10T03:55:00.000Z
NULLanita2026-08-30T06:15:00.000Z

(5 rows)

Example: News: the newest article of each company (sample data: content-news)

SELECT symbol, published_at, title
FROM news
LATEST ON published_at PARTITION BY symbol
ORDER BY published_at DESC;

Result:

symbol (STRING)published_at (TIMESTAMP)title (STRING)
COAST2026-09-02T03:15:00.000ZCoastal Bank merger talks
NULL2026-09-01T02:15:00.000ZMarket index closes at 2,840
VOLT2026-08-15T04:15:00.000ZHydropower company plans IPO
CITY2026-08-01T05:45:00.000Zसिटी बैंकको नाफा बढ्यो

(4 rows)

Example: Accounting: the last journal line of each account (sample data: query-app)

SELECT account, entry_date, debit, credit, memo
FROM ledger
LATEST ON entry_date PARTITION BY account
ORDER BY account;

Result:

account (INT)entry_date (TIMESTAMP)debit (DECIMAL(2))credit (DECIMAL(2))memo (STRING)
10002026-09-05T00:00:00.000ZNULL25000.00September rent
11002026-09-10T00:00:00.000Z12600.00NULLSell 20 CITY at 630
12002026-09-10T00:00:00.000ZNULL10300.00Sell 20 CITY at 630
20002026-09-03T00:00:00.000Z257500.00NULLPay the broker
30002026-09-01T00:00:00.000ZNULL500000.00Owner puts money in the bank
40002026-09-08T00:00:00.000ZNULL6250.00CITY cash dividend
41002026-09-10T00:00:00.000ZNULL2300.00Sell 20 CITY at 630
50002026-09-03T00:00:00.000Z1030.00NULLCommission on the CITY buy
51002026-09-05T00:00:00.000Z25000.00NULLSeptember rent

(9 rows)

WHERE with LATEST ON

Syntax:

SELECT ... FROM table
WHERE condition
LATEST ON time_column PARTITION BY column, ...

WHERE removes rows first. LATEST ON then picks the newest of the rows that are left. So WHERE changes which row is the newest.

Example: The last price of each symbol before 13:30 Nepal time (sample data: sample)

SELECT symbol, ltp, timestamp
FROM live_data
WHERE timestamp < '2026-09-10T13:30:00+05:45'
LATEST ON timestamp PARTITION BY symbol;

Result:

symbol (SYMBOL)ltp (DOUBLE)timestamp (TIMESTAMP)
CITY515.62026-09-10T07:15:00.000Z
COAST391.42026-09-10T07:15:00.000Z
TELCO8692026-09-10T07:15:00.000Z
VOLT1852026-09-10T07:15:00.000Z

(4 rows)

Example: The same text as the 006 app (live_movers.go) (sample data: sample)

SELECT symbol, ltp, point_change, pct_change, volume
FROM live_data
WHERE symbol IN ('CITY', 'COAST') AND timestamp >= '2026-09-10T00:00:00.000000Z'
LATEST ON timestamp PARTITION BY symbol;

Result:

symbol (SYMBOL)ltp (DOUBLE)point_change (DOUBLE)pct_change (DOUBLE)volume (LONG)
CITY527.113.92.7175490
COAST401.92.80.735210

(2 rows)

Example: Wrong and right: symbols whose LAST change is below zero (sample data: sample)

-- Wrong: WHERE runs first, so you get the last FALLING row of each symbol (old rows).
SELECT symbol, pct_change, timestamp
FROM live_data
WHERE pct_change < 0
LATEST ON timestamp PARTITION BY symbol;

-- Right: take the newest row first, then filter.
SELECT symbol, pct_change, timestamp
FROM (SELECT symbol, pct_change, timestamp FROM live_data LATEST ON timestamp PARTITION BY symbol) t
WHERE pct_change < 0;

Result:

SELECT symbol, pct_change, timestamp FROM live_data WHERE pct_change < 0 LATEST ON timestamp PARTITI

symbol (SYMBOL)pct_change (DOUBLE)timestamp (TIMESTAMP)
CITY-0.042026-09-10T05:20:00.000Z
COAST-1.932026-09-10T07:15:00.000Z
TELCO-1.362026-09-10T07:15:00.000Z
VOLT-0.862026-09-10T09:14:00.000Z

(4 rows)

SELECT symbol, pct_change, timestamp FROM (SELECT symbol, pct_change, timestamp FROM live_data LATES

symbol (SYMBOL)pct_change (DOUBLE)timestamp (TIMESTAMP)
VOLT-0.862026-09-10T09:14:00.000Z

(1 row)

Example: The last close of 2025 (the year before) (sample data: sample)

SELECT time, symbol, close
FROM ochl_day
WHERE time IN '2025'
LATEST ON time PARTITION BY symbol;

Result:

time (TIMESTAMP)symbol (SYMBOL)close (DOUBLE)
2025-12-31T00:00:00.000ZCITY542.4
2025-12-31T00:00:00.000ZCOAST426.5
2025-12-31T00:00:00.000ZVOLT194.3

(3 rows)

LATEST ON with other clauses

Syntax:

SELECT ... FROM table [WHERE ...]
LATEST ON time_column PARTITION BY column, ...
[ORDER BY ...] [LIMIT n]

The other parts of the query see only the kept rows.

Example: Top 2 gainers right now (sample data: sample)

SELECT symbol, ltp, pct_change
FROM live_data
LATEST ON timestamp PARTITION BY symbol
ORDER BY pct_change DESC
LIMIT 2;

Result:

symbol (SYMBOL)ltp (DOUBLE)pct_change (DOUBLE)
CITY527.12.71
TELCO897.71.9

(2 rows)

Example: Up or down, with CASE (sample data: sample)

SELECT symbol, pct_change,
       CASE WHEN pct_change > 0 THEN 'up' WHEN pct_change < 0 THEN 'down' ELSE 'flat' END AS direction
FROM live_data
LATEST ON timestamp PARTITION BY symbol
ORDER BY symbol;

Result:

symbol (SYMBOL)pct_change (DOUBLE)direction (STRING)
CITY2.71up
COAST0.7up
TELCO1.9up
VOLT-0.86down

(4 rows)

Example: Aggregates run after LATEST ON: one row per symbol is left (sample data: sample)

SELECT symbol, count(*) AS rows_left
FROM live_data
LATEST ON timestamp PARTITION BY symbol;

Result:

symbol (SYMBOL)rows_left (LONG)
CITY1
COAST1
TELCO1
VOLT1

(4 rows)

Errors

Syntax:

LATEST ON time_column PARTITION BY column, ...

The common mistakes and their messages.

MistakeMessage
LATEST ON timestamp without PARTITION BYexpected PARTITION BY after LATEST ON timestamp
the column after LATEST ON is not a timeLATEST ON needs a TIMESTAMP or DATE column
an unknown columnLATEST ON: unknown column '...'
a query with a JOINLATEST ON works on a single table (no joins)
LATEST BY on a table without a time columnLATEST BY needs a table with a time column

Example: PARTITION BY is needed (sample data: sample; shows an error)

SELECT symbol, ltp FROM live_data LATEST ON timestamp;

Result:

Error: line 1, column 54: expected PARTITION BY after LATEST ON timestamp, as in LATEST ON timestamp PARTITION BY symbol, but found ';'

Example: The column must be a time (sample data: sample; shows an error)

SELECT symbol, ltp FROM live_data LATEST ON symbol PARTITION BY symbol;

Result:

Error: LATEST ON needs a TIMESTAMP or DATE column, 'symbol' is SYMBOL

Example: No joins (sample data: sample; shows an error)

SELECT l.symbol, s.name, l.ltp
FROM live_data l JOIN securities s ON s.symbol = l.symbol
LATEST ON timestamp PARTITION BY symbol;

Result:

Error: LATEST ON works on a single table (no joins)

Example: The fix: LATEST ON in a subquery, then the join (sample data: sample)

SELECT l.symbol, s.name, l.ltp, l.pct_change
FROM (SELECT symbol, ltp, pct_change FROM live_data LATEST ON timestamp PARTITION BY symbol) l
JOIN securities s ON s.symbol = l.symbol
ORDER BY l.pct_change DESC;

Result:

symbol (SYMBOL)name (STRING)ltp (DOUBLE)pct_change (DOUBLE)
CITYCity Bank Limited527.12.71
TELCONorthwind Telecom Limited897.71.9
COASTCoastal Bank Limited401.90.7
VOLTVolt River Hydropower Limited184-0.86

(4 rows)

Example: QuestDB's LATEST BY: the same as LATEST ON the time column (sample data: sample)

SELECT symbol, ltp FROM live_data LATEST BY symbol ORDER BY symbol;
SELECT symbol, ltp FROM live_data LATEST ON timestamp PARTITION BY symbol ORDER BY symbol;

Result:

SELECT symbol, ltp FROM live_data LATEST BY symbol ORDER BY symbol

symbol (SYMBOL)ltp (DOUBLE)
CITY527.1
COAST401.9
TELCO897.7
VOLT184

(4 rows)

SELECT symbol, ltp FROM live_data LATEST ON timestamp PARTITION BY symbol ORDER BY symbol

symbol (SYMBOL)ltp (DOUBLE)
CITY527.1
COAST401.9
TELCO897.7
VOLT184

(4 rows)

Example: LATEST BY needs a time-series table (sample data: sample; shows an error)

SELECT id FROM brokers LATEST BY id;

Result:

Error: LATEST BY needs a table with a time column (a TIMESERIES table); for other tables write LATEST ON <time column> PARTITION BY ...