The Semantic Model
Trilogy states that it has an 'inline semantic model' that supports iteration just like SQL. What is it, actually?
It consists of 3 key statements that produce semantic effects. These are just like any other trilogy statement - they are run in inline, so you can iteratively create, define, and extend a model.
There is not a difference between the semantic language and the query language - think of it like DDL vs Select in SQL.
Concept Declaration
Concepts
are the key unit. They have a name, a type, and optionally a dependent relationship with other concepts.
Keys
The most basic declaration is a key.
key order_id int;
Properties
We can imagine an order id uniquely identifies an order, but there are other things about an order we might want to know.
Those are called properties.
Property declarations have a set of dependent keys assigned before the name name - <key1,key2...>.<name>
.
Tips
Brackets are optional when you have a single key - <key1>.val
and key1.val
will be treated the same
property order_id.product string;
property <order_id>.placed datetime;
property order_id.revenue float;
A property defines a dependent relationship that will be used for aggregation and simplification. If we say every order has a revenue, if we try to get order revenue, we first need to get a set of rows with one order_id and one revenue value per row, before we aggregate.
We can also drop revenue from inferred joins if order_id is present.
Transformations
Transformations represent a derivation of a new concept from other concepts. They should use the keyword auto
, and the compiler will determine their type.
auto product_revenue_rank <- rank product by sum(revenue) by product desc;
Constants
Constants are a special subset of transformations where the right side is a static expression. They can undergo additional optimization.
const meaning_of_life <- 49;
Datasources
Datasources define where we get data from. They are the inputs to the resolution graph. Typically they will be tables in a database, though they can also be queries.
A datasource has a name, a mapping of columns on the asset (physical names) to concepts, a grain (the PK of the table, expressed as concepts), and a physical database address.
datasource order_data
(
ord_id:order_id,
ord_rev:revenue,
)
grain (order_id)
address orders;
To use a query - useful for testing - you replace the 'address' with a 'query'.
datasource
(ord_id:order_id,
ord_rev:revenue,)
grain (order_id)
query '''
SELECT
1 as ord_id, 1.23 as ord_rev
UNION ALL
SELECT
2 as ord_id, 4.0 as ord_rev
'''
;
Merge Statements
Merge statements let you merge one concept into another. This can either be used to bridge two models or to express synonym relationships.
For example
key number int;
key number_size string;
key _number_size <- len(number::string);
merge _number_size into number_size;