I'm trying to do some analytics using Postgres, where I do have 2 tables, called: predictionstate and pageviews.
The predictionstate table:
This table contains the columns with our algorithm outcomes, using the following structure:
- id (
{company_identifier}:{user_identifier}) - model (reference string value)
- prediction (float number between 0.0 and 1.0)
The pageviews table:
This table contains user information, using the following structure:
- company_identifier
- user_identifier
- pageview_current_url_type
Question
I'm trying to get the data based on our best model, to analyze how accurate it is, where basically I need to know to create the Segments and count how many members I do have on it. The following code does that:
WITH ranges AS (
SELECT
myrange::text || '-' || (myrange + 0.1)::text AS segment,
myrange as r_min, myrange + 0.1 as r_max
FROM generate_series(0.0, 0.9, 0.1) AS myrange
)
SELECT
SPLIT_PART(p.id, ':', 1) as company_identifier,
p.model,
r.segment,
COUNT(DISTINCT(SPLIT_PART(p.id, ':', 2))) as "segment_users"
FROM
ranges r
INNER JOIN predictionstate p ON p.prediction BETWEEN r.r_min AND r.r_max
GROUP BY company_identifier, p.model, r.segment
ORDER BY company_identifier, p.model, r.segment;
But the issue that I have, since I don't know exactly how to do it, it's that for each (company, model, segment), and need to get the data of how accurate it is, querying the pageviews table and identifying the pageview_current_url_type == 'BUYSUCCESS'.
What I tried, but didn't work:
WITH ranges AS (
SELECT
myrange::text || '-' || (myrange + 0.1)::text AS segment,
myrange as r_min, myrange + 0.1 as r_max
FROM generate_series(0.0, 0.9, 0.1) AS myrange
)
SELECT
SPLIT_PART(p.id, ':', 1) as company_identifier,
p.model,
r.segment,
COUNT(DISTINCT(SPLIT_PART(p.id, ':', 2))) as "segment_users",
b.n as "converted_users"
FROM
ranges r,
(
SELECT COUNT(DISTINCT(pvs.user_identifier)) as n
FROM pageviews pvs
INNER JOIN (
SELECT
SPLIT_PART(id, ':', 1) as company_identifier,
SPLIT_PART(id, ':', 2) as user_identifier
FROM predictionstate ps
WHERE prediction BETWEEN r.r_min AND r.r_max ) users
ON (
pvs.user_identifier = users.user_identifier AND
pvs.company_identifier= users.company_identifier)
WHERE pageview_current_url_type = 'BUYSUCCESS'
) b
INNER JOIN predictionstate p ON p.prediction BETWEEN r.r_min AND r.r_max
GROUP BY company_identifier, p.model, r.segment
ORDER BY company_identifier, p.model, r.segment;
TL;DR: I need to count a JOIN based on the main query users.
EDIT:
I added an SQL Fiddle https://www.db-fiddle.com/f/5sQiZD6mHwdnwvVfvL9MAh/0 .
What I want to know, for those segment_users, how many of them have a pageview_current_url_type = 'BUYSUCCESS', addind one more column to the result: segmented_really_bought.
EDIT 2: One more attempt not working (ERROR: column "p.id" must appear in the GROUP BY clause or be used in an aggregate function)
WITH ranges AS (
SELECT
myrange::text || '-' || (myrange + 0.1)::text AS segment,
myrange as r_min, myrange + 0.1 as r_max
FROM generate_series(0.0, 0.9, 0.1) AS myrange
)
SELECT
SPLIT_PART(p.id, ':', 1) as company_identifier,
p.model,
r.segment,
COUNT(DISTINCT(SPLIT_PART(p.id, ':', 2))) as "segment_users",
COUNT(b.*) as "converted_users"
FROM
ranges r
INNER JOIN predictionstate p ON p.prediction BETWEEN r.r_min AND r.r_max
INNER JOIN (
SELECT users.company_identifier, COUNT(users.user_identifier) AS n
FROM pageviews
INNER JOIN (
SELECT SPLIT_PART(ps.id, ':', 2) AS user_identifier,
SPLIT_PART(ps.id, ':', 1) AS company_identifier
FROM predictionstate ps
WHERE provider_id=47 AND
prediction > 0.7
) users ON (
pageviews.user_identifier=users.user_identifier AND
pageviews.company_identifier=users.company_identifier
)
WHERE pageview_current_url_type='BUYSUCCESS'
GROUP BY users.company_identifier
) AS b
ON (
b.company_identifier = company_identifier
)
GROUP BY company_identifier, p.model, r.segment
ORDER BY company_identifier, p.model, r.segment;
EDIT 3: Added the desired output
Generated using this code: https://gist.github.com/brunoalano/479265b934a67dc02092fb54a846fe1e
company, model, segment, segment_users, really_bought
company_a, model_a, 0.3-0.4, 1, 3
company_a, model_a, 0.5-0.6, 1, 1
company_a, model_b, 0.2-0.3, 1, 3
company_a, model_c, 0.2-0.3, 1, 1
company_a, model_c, 0.7-0.8, 1, 3
company_b, model_a, 0.3-0.4, 3, 2
company_b, model_b, 0.5-0.6, 2, 1
company_b, model_b, 0.6-0.7, 1, 1
company_b, model_c, 0.5-0.6, 1, 0
company_b, model_c, 0.8-0.9, 1, 1