Skip to content

Snowflake #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions Advanced features/Custom_moving_mau_window.sql
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
--In this query we create a time slice by extrapolating the days between two fixed dates
--this is then joined onto the user activity of x days in the past. And next we count the unique number of users .
WITH dates AS
(SELECT DAY::date
FROM
(SELECT (CURRENT_DATE-30)::TIMESTAMP AS date_range
UNION SELECT CURRENT_DATE::TIMESTAMP)AS ts timeseries DAY AS '1 days' over (
ORDER BY date_range)),
WITH dates AS (
SELECT DISTINCT EVENTDATE AS DAY
FROM events
WHERE EVENTDATE BETWEEN current_date - 30 AND current_date),
activity AS
(SELECT DISTINCT event_date,
user_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ with firstValues as (
group by userId, eventTimestamp)
, results as (
select userID
, TIMESTAMPADD(minute, case when CHAR_LENGTH(TZO)=5 then CAST(substring(tzo, 1,1)||'1' as INTEGER) *-- get positive vs negative tzoffset
, TIMESTAMPADD(minute, case when LEN(TZO)=5 then CAST(substring(tzo, 1,1)||'1' as INTEGER) *-- get positive vs negative tzoffset
(CAST(substring(tzo, 2,2) as INTEGER)*60 + cast(substring(tzo, 4,2) as INTEGER)) else null --get tzoffset in minutes
end ,startTs )as localEventTimestamp
from firstValues)
Expand Down
2 changes: 1 addition & 1 deletion Advanced features/SessionCounter example.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ WITH DATA AS
SELECT eventName,
count(*) AS events,
count(DISTINCT userId) AS users,
round(count(*) / count(DISTINCT userId),2.0) AS 'ev per user in first session'
round(count(*) / count(DISTINCT userId),2.0) AS "ev per user in first session"
FROM DATA
WHERE sessionCounter = 0
GROUP BY eventName
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
--Find the last UiName per user and compare these for current players and players that haven't been playing for a while
--Find the last missionID per user and compare these for current players and players that haven't been playing for a while
WITH DATA AS
(SELECT userId,
eventTimestamp,
first_value(UIName
first_value(missionID
IGNORE nulls) over (partition BY userId
ORDER BY eventTimestamp) AS lastValue --get the first ever value backwards
FROM EVENTS
WHERE sessionId IS NOT NULL --exclude non-gameplay events such as the sending of a notification
) ,aggregates AS
(SELECT userId,
max(eventTimestamp)::date AS last_seen_date,
MAX (lastValue) AS lastUiName
MAX (lastValue) AS lastMissionID
FROM DATA
GROUP BY userId)
SELECT lastUiName,
SELECT lastMissionID,
count(CASE
WHEN last_seen_date> CURRENT_DATE-7 THEN 1
ELSE NULL
Expand All @@ -23,4 +23,4 @@ SELECT lastUiName,
ELSE NULL
END) lapsedPlayers
FROM aggregates
GROUP BY lastUiName
GROUP BY lastMissionID
11 changes: 7 additions & 4 deletions Advanced features/time_slice_concurrency.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
--create a dataset with timestamps between two points at regular intervals
--join sessions on these intervals if they start before and end after this point in time.
--Count the number of sessions on these intervals.
with timeslots as (select slice_time
from (select (CURRENT_DATE-10)::timestamp as date_range union select now())as ts
timeseries slice_time as '10 minutes' over (order by date_range)),
sessions as (select userid, sessionid, min(eventTimestamp) as sessionStart, max(eventTimestamp) as sessionEnd
with timeslots as (
SELECT DISTINCT TIME_SLICE(EVENTTIMESTAMP, 10, 'MINUTE') AS slice_time
FROM events
WHERE EVENTTIMESTAMP BETWEEN CURRENT_TIMESTAMP - INTERVAL '10 day' AND CURRENT_TIMESTAMP
),
sessions as (
select userid, sessionid, min(eventTimestamp) as sessionStart, max(eventTimestamp) as sessionEnd
FROM events
WHERE eventTimestamp between (CURRENT_DATE-10) and now()
and sessionId is not null
Expand Down
1 change: 1 addition & 0 deletions Advanced features/transactions_per_clientVersion.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
--Since the clientVersion is sent in on the gameStarted event at the start of every session but not on each event we can't just filter events by clientVersion in one go.
--However we can extrapolate the clientVersion using an analytic function (with the OVER statement)
--As Snowflake provides you with 12 months worth of data, it is recommeneded that you restrict this query as it will otherwise take a very long time to process.
with data as (
select last_value(clientVersion ignore nulls) over (partition by userId order by eventId) as currentClientversion
,userId
Expand Down
2 changes: 1 addition & 1 deletion KPIs/ARPDAU_and_revenue_with_smartads.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ select eventdate,
round(
(sum(convertedproductAmount)+sum(adEcpm/1000))/100/count(distinct userid)
,4)::float as ARPDAU,
(sum(convertedproductAmount)+sum(adEcpm)/1000)/100::float as 'revenue for both IAP and SmartAds'
(sum(convertedproductAmount)+sum(adEcpm)/1000)/100::float as "revenue for both IAP and SmartAds"
from events
where eventdate between current_date -30 and current_date
group by eventdate
Expand Down
2 changes: 1 addition & 1 deletion KPIs/First_IAP_by_transactionName.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ where convertedProductAmount>0 and revenueValidated in (0,1)
)
select
transactionName,
count(*) as 'IAP count',
count(*) as "IAP count",
sum(convertedproductAmount)/100::float as Revenue
from transactions
where transactionNumber = 1
Expand Down
3 changes: 1 addition & 2 deletions KPIs/IAP_per_platform_per_day.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ WITH data AS (
FROM events e
WHERE
e.eventname IN ( 'newPlayer', 'gameStarted', 'transaction' )
AND gauserstartdate > current_date - 31)

AND gauserstartdate > current_date - 31)
SELECT daynumber,
COUNT(DISTINCT(CASE WHEN platform LIKE 'IOS%' THEN userid END)) AS "iOS Users",
COUNT(DISTINCT(CASE WHEN platform LIKE 'IOS%'
Expand Down
2 changes: 1 addition & 1 deletion KPIs/Mission Starters vs Completers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ WITH DATA AS
FROM events
WHERE missionName IS NOT NULL), nonCompletionData AS
(SELECT missionName,
count(DISTINCT CASE WHEN missionStartedFlag THEN userId ELSE NULL END) AS players,
count(DISTINCT CASE WHEN missionStartedFlag = 1 THEN userId ELSE NULL END) AS players,
count(DISTINCT CASE WHEN missionStartedFlag = 1
AND missionCompletedFlag = 1 THEN userId ELSE NULL END) AS completedPlayers,
count(DISTINCT CASE WHEN missionStartedFlag = 1
Expand Down
10 changes: 5 additions & 5 deletions KPIs/Time_spent_per_level.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ WITH DATA AS
msSinceLastEvent
FROM EVENTS)
SELECT coalesce(current_level, 0) AS LEVEL,--replace not known yet with level 0
sum(msSinceLastEvent)/1000 AS 'Seconds Spent On Level',
count(DISTINCT userId) AS 'Number of users',
count(DISTINCT eventDate) AS 'Total days spent',
count(DISTINCT eventDate)/count(DISTINCT userId) AS 'average days spent',
sum(msSinceLastEvent)/1000/count(DISTINCT userId) AS 'average seconds in game spent on level'
sum(msSinceLastEvent)/1000 AS "Seconds Spent On Level",
count(DISTINCT userId) AS "Number of users",
count(DISTINCT eventDate) AS "Total days spent",
count(DISTINCT eventDate)/count(DISTINCT userId) AS "average days spent",
sum(msSinceLastEvent)/1000/count(DISTINCT userId) AS "average seconds in game spent on level"
FROM DATA
GROUP BY current_level
ORDER BY current_level
1 change: 1 addition & 0 deletions KPIs/average_mission length.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ WITH missions AS
(SELECT userId,
missionGroup,
missionID,
eventName
sum(msSinceLastEvent) over (partition BY missionGroup, userId
ORDER BY eventTimestamp)AS MissionCompletedTime
FROM missions
Expand Down
12 changes: 6 additions & 6 deletions KPIs/campaign_conversion_with_window.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ COALESCE(stepID,1) as stepID,
min(eventTimestamp) as stepTime,
count(userID) over (partition by COALESCE(stepID,1), eventDate order by min(eventTimestamp)) as total_participants
from events
where eventName = 'outOfGameSend'
and communicationState = 'SENT'
where eventName = "outOfGameSend"
and communicationState = "SENT"
and campaignID = 100--the ID of the campaign
and stepType = 'STANDARD'
and stepType = "STANDARD"
group by userID, COALESCE(stepID,1), eventDate
)
select c.stepTime::date as 'Date', c.stepID AS Step, max(total_participants) as Participants, count(distinct e.userID) as 'Occurred', round(count(distinct e.userID)/max(total_participants)*100,2)::float as '%Occurrence'
select c.stepTime::date as "Date", c.stepID AS Step, max(total_participants) as Participants, count(distinct e.userID) as "Occurred", round(count(distinct e.userID)/max(total_participants)*100,2)::float as "%Occurrence"
from in_campaign c left join events e on e.userID = c.userID
and e.eventTimestamp > c.stepTime
and e.eventTimestamp < c.stepTime + interval '7 day'
and e.eventName = 'gameStarted'
and e.eventTimestamp < c.stepTime + interval "7 day"
and e.eventName = "gameStarted"
group by c.stepID, c.stepTime::date
order by c.stepTime::date, c.stepID, Participants
1 change: 0 additions & 1 deletion KPIs/count_days_until_first-purchase.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ WITH userPurchases AS (
FROM fact_user_sessions_day
WHERE revenue > 0
)

SELECT
daysSinceInstall AS daysUntilFirstPurchase,
COUNT(DISTINCT user_id) AS userCount
Expand Down
1 change: 0 additions & 1 deletion KPIs/hours_until_first_purchase.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ WITH transactions AS (
eventname IN ( 'transaction', 'newPlayer', 'gameStarted' )
AND gauserstartdate > (SELECT Min(eventtimestamp) FROM EVENTS)
)

SELECT
userid AS userId,
firsteventtimestamp AS userFirstSeen,
Expand Down
16 changes: 5 additions & 11 deletions KPIs/in_game_test_event.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,26 @@ WITH relevant_data AS (
responseVariantName,
responseMessageSequence,
eventName,
--Check if the next event for this user is the test event
lead(eventName = 'gameStarted') OVER ( userWindow ) AS nextEventIsTestEvent,
--Get the time of the following event
lead(eventTimestamp) OVER ( userWindow ) AS nextTimestamp
lead(eventName = 'gameStarted') OVER (PARTITION BY userId ORDER BY eventTimestamp) AS nextEventIsTestEvent,
lead(eventTimestamp) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS nextTimestamp
FROM events
WHERE ((eventName = 'engageResponse' and responseEngagementName = 'A/B test campaign'
)
OR (eventName = 'gameStarted'
)
)
WINDOW userWindow AS (PARTITION BY userId ORDER BY eventTimestamp )
), results AS (
SELECT
eventDate AS Date,
responseVariantName AS Variant,
responseMessageSequence AS Step,
count(DISTINCT userID) AS Participants,
-- Get the number of people who reach the test event within the interval
count(DISTINCT CASE WHEN nextEventIsTestEvent AND (nextTimestamp - eventTimestamp) <= '1 days' :: INTERVAL
THEN userId END) AS Occurred
count(DISTINCT CASE WHEN nextEventIsTestEvent AND datediff(d, eventTimestamp, nextTimestamp) <= 1
THEN userId END) AS Occurred
FROM relevant_data
WHERE (eventName = 'engageResponse')
GROUP BY eventDate, responseVariantName, responseMessageSequence
)
SELECT
*,
round(Occurred / Participants * 100, 2) :: FLOAT AS "Occurred %"
FROM results
ORDER BY Date, Variant, Step
round(Occurred / Participants * 100, 2) :: FLOAT AS "Occurred %"
75 changes: 52 additions & 23 deletions KPIs/median_and_average_session_times.sql
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
--Get the median and average session times
--The median times can only be retrieved in an analytic function
WITH DATA AS
(SELECT min(eventDate) AS eventDate,
sessionId,
userId,
sum(msSinceLastEvent) AS sessionDurationMs,
count(*)AS eventCount
FROM EVENTS
GROUP BY sessionId,
userId) ,medianValues as
(SELECT *, MEDIAN(sessionDurationMs) OVER (PARTITION BY eventDate) AS medianSessionTime
FROM DATA
WHERE eventCount>1-- exclude sessions with just one event
with data as (
select
min(eventDate) as eventDate,
sessionId,
userId,
sum(msSinceLastEvent) as sessionDurationMs,
count(*)as eventCount
from
EVENTS
group by
sessionId,
userId) ,
medianValues as (
select
*,
MEDIAN(sessionDurationMs) over (partition by eventDate) as medianSessionTime
from
data
where
eventCount>1
-- exclude sessions with just one event
)
SELECT eventDate,
round(avg(sessionDurationMs)/1000,2.0) AS 'Mean session time in seconds',
(avg(sessionDurationMs)::varchar||'ms')::interval AS 'Mean session time as interval',
round(medianSessionTime/1000, 2.0) AS 'Medain session time in seconds',
(medianSessionTime::varchar||'ms')::interval AS 'Median session time as interval',
count(DISTINCT userId) AS 'Sample size users',
count(DISTINCT sessionId) AS 'Sample size sessions'
FROM medianValues
GROUP BY eventDate,
medianSessionTime
ORDER BY eventDate DESC
select
eventDate,
round(avg(sessionDurationMs)/ 1000, 2.0) as "Mean session time in seconds",
case -- format time into an interval
when avg(sessionDurationMs) < 0 then '-' || TO_CHAR(TRUNC(ABS(avg(sessionDurationMs))/ 3600000), 'FM9900') || ':' ||
TO_CHAR(TRUNC(mod(ABS(avg(sessionDurationMs)), 3600000)/ 60000), 'FM00') || ':' ||
TO_CHAR(TRUNC(mod(ABS(avg(sessionDurationMs)), 60000)/ 1000), 'FM00') || '.' ||
TO_CHAR(mod(ABS(avg(sessionDurationMs)), 1000), 'FM000')
else TO_CHAR(TRUNC(avg(sessionDurationMs)/ 3600000), 'FM9900') || ':' ||
TO_CHAR(TRUNC(mod(avg(sessionDurationMs), 3600000)/ 60000), 'FM00') || ':' ||
TO_CHAR(TRUNC(mod(avg(sessionDurationMs), 60000)/ 1000), 'FM00') || '.' ||
TO_CHAR(mod(avg(sessionDurationMs), 1000), 'FM000') end as "Mean session time as interval",
round(medianSessionTime / 1000, 2.0) as "Medain session time in seconds",
case
when medianSessionTime < 0 then '-' || TO_CHAR(TRUNC(ABS(medianSessionTime)/ 3600000), 'FM9900') || ':' ||
TO_CHAR(TRUNC(mod(ABS(medianSessionTime), 3600000)/ 60000), 'FM00') || ':' ||
TO_CHAR(TRUNC(mod(ABS(medianSessionTime), 60000)/ 1000),
'FM00') || '.' || TO_CHAR(mod(ABS(medianSessionTime), 1000), 'FM000')
else TO_CHAR(TRUNC(medianSessionTime/ 3600000), 'FM9900') || ':' ||
TO_CHAR(TRUNC(mod(medianSessionTime, 3600000)/ 60000), 'FM00') || ':' ||
TO_CHAR(TRUNC(mod(medianSessionTime, 60000)/ 1000), 'FM00') || '.' ||
TO_CHAR(mod(medianSessionTime, 1000), 'FM000') end as "Median session time as interval",
count(distinct userId) as "Sample size users",
count(distinct sessionId) as "Sample size sessions"
from
medianValues
group by
eventDate,
medianSessionTime
order by
eventDate desc
16 changes: 8 additions & 8 deletions KPIs/retention_for_min_event_date_only.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ group by player_start_date,
), retention AS
( SELECT player_start_date,
COUNT (DISTINCT CASE WHEN n = 0 THEN user_id ELSE NULL END)AS installs,
COUNT (DISTINCT CASE WHEN n = 1 THEN user_id ELSE NULL END)AS 'day 1 retention',
COUNT (DISTINCT CASE WHEN n = 7 THEN user_id ELSE NULL END)AS 'day 7 retention',
COUNT (DISTINCT CASE WHEN n = 14 THEN user_id ELSE NULL END)AS 'day 14 retention',
COUNT (DISTINCT CASE WHEN n = 30 THEN user_id ELSE NULL END)AS 'day 30 retention'
COUNT (DISTINCT CASE WHEN n = 1 THEN user_id ELSE NULL END)AS "day 1 retention",
COUNT (DISTINCT CASE WHEN n = 7 THEN user_id ELSE NULL END)AS "day 7 retention",
COUNT (DISTINCT CASE WHEN n = 14 THEN user_id ELSE NULL END)AS "day 14 retention",
COUNT (DISTINCT CASE WHEN n = 30 THEN user_id ELSE NULL END)AS "day 30 retention"
FROM DATA
GROUP BY player_start_date)
SELECT *,
round("day 1 retention"/"installs"*100,2.0) as 'D1%',
round("day 7 retention"/"installs"*100,2.0) as 'D7%',
round("day 14 retention"/"installs"*100,2.0) as 'D14%',
round("day 30 retention"/"installs"*100,2.0) as 'D30%'
round("day 1 retention"/"installs"*100,2.0) as "D1%",
round("day 7 retention"/"installs"*100,2.0) as "D7%",
round("day 14 retention"/"installs"*100,2.0) as "D14%",
round("day 30 retention"/"installs"*100,2.0) as "D30%"
FROM retention
ORDER BY player_start_date DESC

4 changes: 2 additions & 2 deletions KPIs/revenue_per_hour.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
then get the revenue for this hour, the total number of users as well as the total number of spenders within this window.
*/
select date_trunc('hour', eventTimestamp) as time,
to_char(sum(convertedproductamount)/100, '$999,999,999,999.00') as revenue,
to_char(sum(convertedproductamount)/100, '"$"999,999,999,999.00') as revenue,
count(distinct userid) active_users,
count(distinct case when convertedproductamount>0 then userId end) as spenders
from events
where revenuevalidated not in (2,3)
and eventName in ('gameStarted', 'transaction')
and eventTimestamp between now() - interval '100 hours' and now()
and eventTimestamp between current_timestamp() - interval '100 hours' and current_timestamp()
group by 1 order by 1 desc
4 changes: 2 additions & 2 deletions KPIs/revenue_per_item.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ WITH items as
WHERE e.productCategory = 'REAL_CURRENCY'
ORDER BY itemName)
SELECT itemName,
sum(productAmount) as 'items sold',
sum(productAmount) as "items sold",
round(sum(convertedProductAmount)/100,2.0) as revenue,
count(*) as sales
FROM spendings
GROUP BY itemName
order by "revenue" desc
order by revenue desc
12 changes: 6 additions & 6 deletions KPIs/smartads_and_iap_ltv.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ with data as (
gaUserStartdate,
count(distinct userId) as userCount,
sum(case when revenueValidated in (0,1) then convertedProductAmount/100 end) as IapRevenue,
sum(case when eventname = 'adClosed' and adstatus = 'Success' then adEcpm/100000 end) as PredictedAdRevenue
sum(case when eventname = "adClosed" and adstatus = "Success" then adEcpm/100000 end) as PredictedAdRevenue
from events
where gaUserStartDate>= (select min(eventDate) from events)
group by gaUserStartdate)
select
gaUserStartDate as 'install date',
round(IapRevenue/userCount,4)::float as 'IAP LTV',
round(PredictedAdRevenue/userCount,4)::float as 'Predicted Ad LTV',
round((PredictedAdRevenue+IapRevenue)/userCount,4)::float as 'total LTV',
userCount as 'Number of players'
gaUserStartDate as "install date",
round(IapRevenue/userCount,4)::float as "IAP LTV",
round(PredictedAdRevenue/userCount,4)::float as "Predicted Ad LTV",
round((PredictedAdRevenue+IapRevenue)/userCount,4)::float as "total LTV",
userCount as "Number of players"
from data
order by gaUserStartDate
Loading