skip to content

Looker

BI where the model lives in LookML and is version-controlled, so every explore and dashboard derives from one governed definition. Interviewers ask how that differs from tools where each analyst writes their own SQL — the answer is metric consistency.

on this pageshow

questions

6

In Looker, what is the difference between a LookML view and an explore?

level: juniorimportance: must knowfreq 76%

answer

  1. one describes a table, one starts a query
  2. declaring a field does not publish it
  3. joins are declared outside the view file
  4. users open explores, never views directly

basics

~20 s

A LookML view declares the fields — dimensions and measures — available from one table. An explore is the query entry point declared in the model file: it names a base view, joins other views to it, and is what users actually open.

solid answer

~40 s

A **view** is a LookML file describing one table or derived table: a `sql_table_name` plus `dimension` and `measure` declarations naming the columns and aggregates that table can produce. An **explore** is declared in the model file and is the query starting point users see in the UI: it names a base view, `join`s other views with `sql_on` and `relationship`, and controls which fields are exposed. Views are reusable definitions; explores are curated starting points built from them. A field only reaches a business user when some explore includes the view that declares it — which is why "I wrote the dimension and nobody can find it" almost always means the view was never joined into an explore. Note that Looker and Looker Studio are different Google products.

code

lookml · 19 lines
lookml
view: orders {
  sql_table_name: public.orders ;;

  dimension: id {
    primary_key: yes
    type: number
    sql: ${TABLE}.id ;;
  }

  dimension: user_id {
    type: number
    sql: ${TABLE}.user_id ;;
  }

  measure: total_amount {
    type: sum
    sql: ${TABLE}.amount ;;
  }
}

go deeper

for a junior

Be able to say plainly that a view declares fields for one table and an explore is the joined query entry point users open. Knowing which file each lives in is a common screening check.

for a middle

Explain how an explore's joins turn into generated SQL, why Looker only joins the views whose fields were selected, and how fields: and hidden: curate what an explore exposes.

for a senior

Show judgment about explore design: how many explores to expose, when to reuse a view across several join paths, and how to keep a curated business surface rather than a menu of every field in the warehouse.

for a principal

Own the governance argument — why centralizing definitions in Git-tracked LookML changes who can define a metric, and what that costs in developer throughput compared with tools where each analyst writes their own SQL.

## The two halves of a LookML project Looker's modeling language, LookML, separates *what a table can produce* from *what a user is allowed to start a query from*. Those two halves are the view and the explore, and nearly every beginner confusion about Looker dissolves once the split is clear. ## A view: the field dictionary for one table A view lives in a `*.view.lkml` file and describes exactly one physical table, or one derived table. Inside it you declare: - `sql_table_name:` — the table in the warehouse the view maps to. - `dimension:` — a row-level field. Its `sql:` parameter is a non-aggregated expression, usually `${TABLE}.column_name`, where `${TABLE}` is Looker's placeholder for the aliased table in the generated query. - `measure:` — an aggregate: `type: count`, `type: sum`, `type: average`, `type: count_distinct`, or `type: number` with a hand-written expression. - `primary_key: yes` on one dimension — load-bearing, because Looker uses it to keep aggregates correct across joins. A view is *only* a declaration. Writing a view does not put anything in front of a user, does not run any SQL, and does not decide how the table relates to any other table. ## An explore: the query entry point An explore is declared in the model file (`*.model.lkml`), which also carries the `connection:` name and the `include:` statements that pull view files in. An explore names a base view and joins others onto it: ``` explore: orders { join: users { type: left_outer relationship: many_to_one sql_on: ${orders.user_id} = ${users.id} ;; } } ``` When a user picks the **Orders** explore, Looker shows the fields of `orders` and of every joined view, and generates SQL with the base table in the `FROM` clause and joins added only for the views whose fields the user actually selected. The explore is also where you curate: `fields:` limits which fields the explore exposes, `label:` renames it for business users, `hidden: yes` keeps it out of the menu, and filter parameters such as `always_filter` or `sql_always_where` constrain every query it produces. ## Why the split exists One view can be joined into many explores with different join paths, different labels, and different exposed field sets. `users` can be joined to an Orders explore as the customer and to a Support Tickets explore as the reporter — one definition of the user fields, several curated business contexts. If views and explores were the same object you would either duplicate field definitions or force every consumer through one join graph. The split is also the governance story. Analysts and business users work in explores, saved Looks and dashboards; developers work in views and models, in Git branches under Looker's dev mode, and promote to production through a commit and deploy. The definition of *revenue* lives in one measure in one view, so every Look and dashboard that touches it inherits the same expression. ## The failure this causes for beginners The most frequent Looker beginner bug: a dimension or measure is written in a view, the LookML validates, and the field never appears for users. The cause is almost always that no explore includes that view, or that the explore's `fields:` parameter or a `hidden: yes` on the field excludes it. Declaring a field publishes nothing by itself. A second one is expecting a view to behave like a database view. It is not one — a plain view maps onto a table that already exists; nothing is created in the warehouse unless you write a derived table and persist it. ## Looker is not Looker Studio Looker and Looker Studio (formerly Google Data Studio) are separate Google products with separate interfaces. Looker's whole premise is the LookML modeling layer described here, version-controlled in Git and governed centrally. Looker Studio is a lighter self-serve reporting tool where each report author wires up their own connectors and calculated fields. Interviewers do use the confusion as a filter, so name the right one when you answer.

  • Which LookML file does an explore live in, and what else is in that file?
    Explores are declared in a model file (`*.model.lkml`), which also carries the `connection:` name for the database and the `include:` statements that pull in view files. Views live in their own `*.view.lkml` files and contain no join logic at all.
  • Can the same view be used by more than one explore?
    Yes, and that is the point of the split. One `users` view can join into an Orders explore as the customer and into a Tickets explore as the reporter, each with its own join path, label, and `fields:` list, while the field definitions stay written once.
  • Is Looker the same thing as Looker Studio?
    No. They are separate Google products. Looker is built on the LookML semantic model, version-controlled in Git, where developers define fields centrally. Looker Studio, formerly Data Studio, is a lighter self-serve reporting tool where each report author configures their own connectors and calculated fields.

A view is an ingredient list for one table; an explore is a menu the kitchen actually lets guests order from, assembled out of several ingredient lists.

saying these in an interview costs you the question

  • Says a LookML view is a database view in the warehouse
  • Thinks declaring a dimension automatically shows it to users
  • Describes an explore as a saved dashboard or report
  • Uses Looker and Looker Studio interchangeably
  • Claims joins are configured inside the view file

context

open as a page

In Looker, why does a summed order amount inflate after joining order items?

level: middleimportance: must knowfreq 55%

basics

~20 s

Joining a one-to-many table fans out the base rows, so a plain SUM adds each order's amount once per matching item. Looker normally corrects this with symmetric aggregates, but only when the view declares a primary key and the measure uses a typed aggregate.

open as a page

In LookML, how do dimensions and measures differ in the SQL Looker generates?

level: middleimportance: should knowfreq 68%

basics

~10 s

A LookML dimension becomes a non-aggregated expression that lands in SELECT and GROUP BY. A measure becomes an aggregate such as SUM or COUNT. Measures may reference dimensions; dimensions may never reference measures.

open as a page

In Looker, how do access_filter and user attributes limit rows an explore returns?

level: seniorimportance: should knowfreq 46%

basics

~20 s

An access_filter declared on a Looker explore maps a field to a user attribute, so every query that explore generates gets a WHERE clause built from the signed-in user's attribute value. It is query-time filtering by the model layer, not database-level security.

open as a page

When should logic live in a Looker PDT rather than an upstream warehouse table?

level: principalimportance: should knowfreq 36%

basics

~20 s

Keep logic in a Looker persistent derived table when it is BI-specific shaping and iteration speed matters. Move it upstream when other tools consume the same result, or when it needs tests, lineage and orchestration alongside the rest of the pipeline.

open as a page

In LookML, what does Liquid templating let you change at query time?

level: middleimportance: nice to knowfreq 26%

basics

~20 s

Liquid is a templating language Looker evaluates while building a query or rendering results, so sql, html, link and label parameters can vary with a field's value, the current filter values, or the signed-in user's attributes.

open as a page