Malloy Documentation
search

Malloy recognizes modeling as a key aspect of data analytics and provides tools that allow for modularity and reusability of definitions. Whereas in SQL, queries generally define all metrics inline, requiring useful snippets to be saved and managed separately, in Malloy, dimensions, measures, and views can be saved and attached to a modeled source, which itself is defined as part of a Malloy document, often referred to as a model.

A Malloy document is a collection of statements, comments, and tags. Statements can be separated with an optional semi-colon for clarity, which helps readability when statements appear on the same line.

Statements

There are four kinds of statements that can appear in a Malloy model:

Import Statements

Import statements allow you to import sources from another .malloy file.

document
import "flights.malloy"

See the Imports section for more information.

Query Statements

A query statement defines a query as a named entity within a model, allowing it to be reused as the basis for other queries.

document
query: flights_by_carrier is duckdb.table('../data/flights.parquet') -> {
  group_by: carrier
  aggregate: flight_count is count()
}

See the Queries section for more information on queries.

Source Statements

In Malloy, a source is the basic unit of reusability for calculations, join relationships, and queries, and can be thought of as a table and a collection of computations and relationships which are relevant to that table.

A source statement defines a source as a reusable part of the model.

document
source: flights2 is duckdb.table('../data/flights.parquet') extend {
  dimension: distance_km is distance * 1.609344

  measure: flight_count is count()

  view: by_carrier is {
    group_by: carrier
    aggregate: flight_count
  }
}

See the Sources section for more information on sources.

Run Statements

Run statements allow you to write queries in a model without naming them, or to indicate to the host application that a particular query should be run. You'll see run statements all over the documentation, usually followed by the results of running that query.

Any query can be run by including it in a run statement.

document
run: flights2 -> { 
  group_by: origin
  aggregate: destination_count is count(destination) 
}
QUERY RESULTS
origindestination_​count
ATL134
CVG127
IAH116
DFW115
ORD91
[
  {
    "origin": "ATL",
    "destination_count": 134
  },
  {
    "origin": "CVG",
    "destination_count": 127
  },
  {
    "origin": "IAH",
    "destination_count": 116
  },
  {
    "origin": "DFW",
    "destination_count": 115
  },
  {
    "origin": "ORD",
    "destination_count": 91
  }
]
SELECT 
   flights2."origin" as "origin",
   count(distinct flights2."destination") as "destination_count"
FROM '../data/flights.parquet' as flights2
GROUP BY 1
ORDER BY 2 desc NULLS LAST

See the Queries section for more information on queries.

Comments

Comments in Malloy can be written with -- (as in SQL) or //. A comment continues until the end of the line.

document
// This is a comment
-- This is also a comment

Tags

Tags are a general-purpose feature of Malloy that allow arbitrary metadata to be attached to various Malloy objects (queries, sources, fields, etc.). One use case for tagging is to attach rendering information to a query:

document
# json
run: flights2 -> {
  group_by: carrier
  aggregate: flight_count
  limit: 2
}
QUERY RESULTS
[
  {
    "carrier": "WN",
    "flight_count": 88751
  },
  {
    "carrier": "US",
    "flight_count": 37683
  }
]
[
  {
    "carrier": "WN",
    "flight_count": 88751
  },
  {
    "carrier": "US",
    "flight_count": 37683
  }
]
SELECT 
   flights2."carrier" as "carrier",
   COUNT( 1) as "flight_count"
FROM '../data/flights.parquet' as flights2
GROUP BY 1
ORDER BY 2 desc NULLS LAST
LIMIT 2

For more information about the rendering tags used in the Malloy rendering library, see the Visualizations section.

For more information about tag semantics, see the Tags section.