Skip to content

Instantly share code, notes, and snippets.

@ryantuck
Last active February 5, 2018 16:21
Show Gist options
  • Save ryantuck/c1da4e19a53755ab9f0024a47ef0530e to your computer and use it in GitHub Desktop.
Save ryantuck/c1da4e19a53755ab9f0024a47ef0530e to your computer and use it in GitHub Desktop.

Get some high-level data on our sends table.

select
    min(sent_on) as first_date,
    max(sent_on) as latest_date,
    count(*) as total_records,
    count(distinct template) as unique_templates,
    count(distinct sent_on) as unique_dates
from
    email.sends
limit 10
;

What dates did we send emails on? How many emails per day?

select
  sent_on as date_sent,
  count(*) as num_emails_sent
from
  email.sends
group by
    1
order by
    2 desc
;

Multiple different ways to cast a timestamp to a date.

select
  created,
  date(created),
  created::date,
  cast(created as date)
from some_table

limit 100

Group by a column that we've casted to a date.

select
  date(created),
  count(*)
from some_table
where created > '2016-01-01'
group by 1
order by 2 desc

limit 100
;

Query the results of a query (this is called using a subquery).

select
    *
from
(
    select
      sends.*,
      case
        when send_id is null then false
        else true
        end as was_opened,
      opened_on - sent_on as days_til_open
    from
      email.sends
      left join
        email.opens
        on sends.id = opens.send_id
) as email_information
where
    days_til_open > 6
limit 100;

Or, use with to create a temporary table for cleaner querying later:

with

email_information as (
    select
      sends.*,
      case
        when send_id is null then false
        else true
        end as was_opened,
      opened_on - sent_on as days_til_open
    from
      email.sends
      left join
        email.opens
        on sends.id = opens.send_id
)


select * from email_information
where days_til_open > 6
limit 100;

Group our results by template and calculate open rate in a few different ways:

with

email_information as (
    select
      sends.*,
      case
        when send_id is null then false
        else true
        end as was_opened,
      opened_on - sent_on as days_til_open
    from
      email.sends
      left join
        email.opens
        on sends.id = opens.send_id
),

template_data as (
    select
        template,
        sum(case
                when was_opened then 1
                else 0
                end
            ) as num_opens,
        count(*) as num_sends
    from
        email_information
    group by template
)

select
    *,
    num_opens * 1.0 / num_sends as open_rate,
    num_opens::numeric / num_sends as open_rate_2,
    cast(num_opens as numeric) / num_sends as open_rate_3
from template_data
limit 100;

Round our open rate results to 2 decimal places:

with

email_information as (
    select
      sends.*,
      case
        when send_id is null then false
        else true
        end as was_opened,
      opened_on - sent_on as days_til_open
    from
      email.sends
      left join
        email.opens
        on sends.id = opens.send_id
),

template_data as (
    select
        template,
        sum(case
                when was_opened then 1
                else 0
                end
            ) as num_opens,
        count(*) as num_sends
    from
        email_information
    group by template
)

select
    *,
    round(num_opens::numeric / num_sends, 2) as open_rate
from template_data
order by open_rate desc
limit 100;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment