Metabase Metadata SQL

This was very helpful! I was able to create a “Top 10 Dashboard” and “Top 10 Question” set of questions going over a recent period of time.

I’d like to be able to find any dashboard associated with a specific question. I have built the query, but in order to use a field filter, I believe I need to go in as an administrator and change the “Type” of the dashboard name field. My questions is…if I’m connecting directly to the Metabase Database, from Metabase, and changing field types (from name to" Category")…does that cause any problems with the Metabase site? Changing the type of a field that is used everywhere in the system seems dangerous. Should I leave this alone? :slight_smile:

@MetaKC When you add Metabase’s own application database to Metabase as a datasource, then the Data Model only has something to do with the datasource - and not the application database itself, that Metabase writes information to.
So you can change anything in the Data Model.
But as always, make sure to have backups, and if you’re using the default H2 database, then you should migrate away:
https://www.metabase.com/docs/latest/operations-guide/migrating-from-h2.html

Thanks for this !
Adding the 2 models I use at the minute:

-- timeseries of cumulated new users
with data as (
    select 
        timestamp :: date as date_at,
        count(user_id) as count
    from activity
    where topic= 'user-joined'
    group by 1
)
select
  date_at,
  sum(count) over (order by date_at asc rows between unbounded preceding and current row) as running_users
from data
-- weeky active users
select
    date_trunc('week', created_at) as week_at,
    count(distinct user_id) as weekly_active_users
from
    core_session
group by 1
order by 1 asc
2 Likes

I’m adding a few queries that are really useful to me and maybe can be helpful to someone else.
I use them after changing the data model that feeds 100s/1000s of queries and I’m absolutely not even considering changing anything by hand!

A) replace anything with a regex within the actual code of my queries

Step 1: identify all the queries contain the term I need to update

SELECT 
    dataset_query,
    *
FROM report_card 
where dataset_query like '%native%'	-- to isolate those in native SQL
and dataset_query ~* 'field\/edit\/\?id=.[\|]{2}your_old_value'

Step 2: update the queries

UPDATE
	report_card
SET 
	dataset_query = REGEXP_REPLACE
	(
	dataset_query,				
	'field\/edit\/\?id=.[\|]{2}your_old_value',
	'field/edit/?id='||'||your_new_value',
	'g'									
	)	
WHERE 
		dataset_query like '%native%'			
		AND dataset_query ~* 'field\/edit\/\?id=.[\|]{2}field_id'

After Step 2 I usually run Step 1 to confirm I have successfully updated everything and then check that all my dashboards are running smoothly

B) Update filters that where once based on my old column_name

Step 1: I find all the filters that rely on my old column_name

SELECT 
* 
FROM public.metabase_field 
WHERE display_name = 'old_column_name'
    OR name = 'old_column_name'
ORDER BY created_at DESC

Step 2: update from old to new column_name ( I usually do it one at the time to double check everything)

UPDATE metabase_field
SET display_name = 'new_column_name'
WHERE display_name = 'old_column_name'

Most viewed dasboards in the last 3 months

    /* Most viewed dasboards in the last 3 months */
select rd.name as DashboardName, count(cu.id) as viewCount, rd.description as DashboardDescription
from core_user cu
INNER JOIN view_log vl on vl.user_id = cu.id
INNER JOIN report_dashboard rd on rd.id = vl.model_id
where vl.model='dashboard' 
-- last 3 months
AND str_to_date(concat(date_format(vl.timestamp, '%Y-%m'), '-01'), '%Y-%m-%d') 
   BETWEEN str_to_date(concat(date_format(date_add(now(6), INTERVAL -3 month), '%Y-%m'), '-01'), '%Y-%m-%d')
   AND str_to_date(concat(date_format(now(6), '%Y-%m'), '-01'), '%Y-%m-%d')

GROUP BY rd.name, rd.description
ORDER BY viewCount DESC
3 Likes

Most viewed questions in the last 3 months

/* Most viewed questions in the last 3 months */
SELECT 
  rc.name AS CardName
, COUNT(vl.user_id) AS viewCount
, rc.description AS CardDescription
FROM view_log vl
INNER JOIN report_card rc ON rc.id = vl.model_id
WHERE vl.model='card' 
-- last 3 months
AND str_to_date(concat(date_format(vl.timestamp, '%Y-%m'), '-01'), '%Y-%m-%d') 
   BETWEEN str_to_date(concat(date_format(date_add(now(6), INTERVAL -3 month), '%Y-%m'), '-01'), '%Y-%m-%d')
   AND str_to_date(concat(date_format(now(6), '%Y-%m'), '-01'), '%Y-%m-%d')

GROUP BY rc.name, rc.description
ORDER BY viewCount DESC

Questions never viewed in the last 3 months

/* Questions never viewed in the last 3 months */
SELECT 
  rc.id
, CONCAT('http://your_base_url', rc.id) AS CardUrl
, rc.name AS CardName
, rc.description AS CardDescription
FROM report_card rc
WHERE rc.id NOT IN (
    SELECT vl.model_id
    FROM view_log vl 
    WHERE vl.model='card' 
    -- last 3 months
    AND str_to_date(concat(date_format(vl.timestamp, '%Y-%m'), '-01'), '%Y-%m-%d') 
       BETWEEN str_to_date(concat(date_format(date_add(now(6), INTERVAL -3 month), '%Y-%m'), '-01'), '%Y-%m-%d')
       AND str_to_date(concat(date_format(now(6), '%Y-%m'), '-01'), '%Y-%m-%d')
)
5 Likes

What format is the dataset query stored in the app DB, and what is the best way to convert/clean after exporting / copying dataset query to obtain pure SQL? @marco

@AndrewMBaines hello, very useful queries, but could you show me where I can run those? of course i cant run in metabase with my db

I just run them from Metabase. Your database should be either Postgres or MySQL. If you're still on H2, you need to migrate now before you lose all your work.

My application database has been Postgres already, but I still could not run those queries. May it be due to that my Metabase is not paid-plan (I mean Pro/Enterprise)?

Nope. Should work on any plan. You just need the details of the database.

Hmm, could you pls show me how to add Metabase’s own application database to Metabase as a datasource? Or any related docs, tks.

@ThaoDinh Go to Admin > Databases and create a new data source, where you input the credentials to your Metabase application database.

1 Like

Hey everyone, I am trying to figure out if it is possible to query for all questions and dashboards that weren't visited in the past few months. Is it possible to do this in the application database?

That's already been answered earlier in this thread.

Got it, thank you!

Hi, I am new to application db. May I know, running_time in query_execution falls under what time format? seconds?

image

@amzar Look at the column descriptions, they are available for most tables and columns.
Specifically query_execution.running_time: The time, in milliseconds, this query took to complete.

1 Like

Thank you for sharing your queries! It was really helpful:)
Additionally I need to show dashboards which appear at the main page of our company metabase page. This dashboards are pinned in our collection Our analytics. Maybe you know where to find pinned dashboards in metabase logs?

Agreed super helpful

  • List of un archived dashboards with last accessed date on the public link
-- using view log table see when cards were last accessed and map the card ids to dashboard ids. 
-- (none of my cards are on more than one dash)
with joined as (
    select 
        view_log.model_id as Model_ID,
        date(max(view_log.timestamp)) as Last_Viewed,
        report_dashboardcard.dashboard_id as Dashboard_ID 
    from
        view_log 
        left join report_dashboardcard on view_log.model_id = report_dashboardcard.card_id 
    where 
        view_log.model = 'card'
        and view_log.user_id is null
    group by 
        Model_ID, 
        Dashboard_ID
),

-- get rid of dashboards that are archived
dashboards as (
    select 
        report_dashboard.id as Dashboard_ID,
        report_dashboard.name as Dashboard_Name
    from 
        report_dashboard
    where
        report_dashboard.archived = false
)

-- join two above tables to link dashboard name to dashboard id
select 
    dashboards.dashboard_name as Dashboard_Name,
    max(joined.last_viewed) as last_viewed 
from 
    joined 
    inner join dashboards on joined.dashboard_id = dashboards.dashboard_id
group by 
    Dashboard_Name
order by 
    last_viewed desc
1 Like