Use sql to calculate a market penetration ratio? - mysql

I have a table 'transactions' of purchasing activity:
customer_id, company, purchaseamount
and am looking for an sql command to output the "market penetration ratio" for a given company:
For example, I want to calculate:
(number of unique customer_id who bought from company == 12) / (total number of unique customer_id)

select count(distinct customer_id) * 100 / (select count(distinct customer_id) from transactions)
from transactions
where customer_id = 12

You can do this using conditional aggregation:
select count(distinct case when company = 12 then customer_id end) / count(distinct customer_id)
from transactions;

The unique number of customer_ids is a single row, so you can just cross join it with the distinct count per company
SELECT company, COUNT (DISTINCT customer_id) / cnt AS penetration_ratio
FROM my_table
CROSS JOIN (SELECT COUNT (DISTINCT customer_id) AS cnt
FROM my_table) t

Related

How to find the repeat customers in the list?

I Have Purchase Table Containing 5 Columns
Columns Names Are
CustomerID, BillID, ProductID, unatity, Payment_Type
Columns Values Are
CID00001, BID00001, PID001, 1, Card
Total Customers Count - 37156
DISTINCT Customers Count - 26053
How to Find the repeat Customers? (37156 - 26053 = 11103)
Aggregation is one way:
SELECT COUNT(*) AS num_repeat
FROM
(
SELECT CustomerID
FROM purchases
GROUP BY CustomerID
HAVING COUNT(*) > 1
) t;
To get the list of repeat customers,
SELECT CustomerID, COUNT(*) AS PurchaseCount
FROM purchases
GROUP BY CustomerID
HAVING COUNT(*) > 1
You can use this :
SELECT * FROM Purchase
WHERE CustomerID
IN(
SELECT CustomerID FROM Purchase
GROUP BY CustomerID HAVING COUNT(*) > 1
)

Replacing a union in MySQL

I’m trying to retrieve the number of unique users that have made a purchase in a monthly basis. This sounds simple but the problem here is that we have three type of products and the purchases of these products are on different tables in which the only common key is the user_id, so in order to find out unique users I have to query the three tables separately, union the results and execute a count distinct.
Here’s an example of what I’m doing right now:
SELECT
month,
count(distinct user_id) as users
FROM
(
SELECT
DATE_FORMAT(purchase_date,’%Y-%m) as month,
user_id
FROM purchases_a
UNION
SELECT
DATE_FORMAT(purchase_date,’%Y-%m) as month,
user_id
FROM purchases_b
UNION
SELECT
DATE_FORMAT(purchase_date,’%Y-%m) as month,
user_id
FROM purchases_c
)
GROUP BY 1
Is this the only way to go? This query takes forever. Thanks!
One method is to use union all in a subquery and then aggregate:
select DATE_FORMAT(purchase_date, '%Y-%m') as month,
count(distinct user_id)
from ((select user_id, purchase_date from purchases_a) union all
(select user_id, purchase_date from purchases_b) union all
(select user_id, purchase_date from purchases_c)
) p
group by month

MySQL group count by 2 columns?

Given a payments table that includes payer_id and recipient_id
And calculating received payments would be:
select COUNT(*) as payer_count, recipient_id
FROM payments
GROUP BY recipient_id
ORDER BY payer_count DESC
how do you calculate: the number of payments that a user is on(a user can be either a payer_id or a recipient_id)?
If is suppose that you want to count - for every person with a particular id - the number of payment transactions in which this person has been involved, then a union all should help:
select person_id, count(*)
from ((select payer_id as person_id from payments) union all (select recipient_id as person_id from payments)) paymentsOfPerson
group by person_id
order by person_id DESC
If payments can also contain records where payer_id = recipient_id (transfer from one account to another account of the same person), then one has to take care that such transfers are not counted twice:
select person_id, count(*)
from ((select payer_id as person_id from payments where payer_id != recepient_id) union all (select recipient_id as person_id from payments)) paymentsOfPerson
group by person_id
order by person_id DESC
One method is UNION ALL before the aggregation:
select id, count(*) as cnt, sum(recipient) as recipient_cnt,
sum(payer) as payer_cnt
from ((select recipient_id as id, 1 as recipient, 0 as payer
from payments
) union all
(select payer_id, 0, 1
from payments
)
) i
group by id;
I think this can solve your problem:
SELECT COUNT(*) as payments_count
, COUNT(DISTINCT payer_id) distinct_payers
, recipient_id
FROM payments
GROUP BY recipient_id
ORDER BY payer_count DESC

Combining Two Select Sum Statements Into One

I have two statements within my table which work fine individually like this:
SELECT fee_earner, (SUM(fe_fees)) AS Total
FROM fees
GROUP BY fee_earner
order by Total desc;
SELECT supervisor, (SUM(sv_fees)) AS Total
FROM fees
GROUP BY supervisor
order by Total desc;
But there are some cases where the fee_earner and supervisor fields have the same person as the data, is there a way to combine these two statements into one to get the overall totals?
You can use union all for this:
SELECT person, sum(fe_fees) as fe_fees, sum(sv_fees) as sv_fees,
(sum(fe_fees) + sum(sv_fees)) as total
FROM ((select fee_earner as person, fe_fees as fe_fees, 0 as sv_fees, 'earner' as which
from fees
) union all
(select supervisor as person, 0 as fe_fees, sv_fees as sv_fees, 'supervisor' as which
from fees
)
) t
GROUP BY person
order by Total desc;
select
fee_earner, SUM(fe_fees) as total, SUM(sv_fees) as total2,
SUM(fe_fees) + SUM(sv_fees) as wholeTotal
from
fees
group by
fee_earner, supervisor
order by
Total desc;

count multiple attributes sql

i am looking for the following output
10 customers with 10 items bought in 2 product groups
8 customers with 10 items bought in 1 product group.
Generally a matrix with a customer count over items bought AND product groups, ie. counting over 2 attributes (items and product group)
I tried the code below, but then it only gives me
1 customer with 10 items and 2 product groups
1 customer with 10 items and 1 product group despite the fact that there is many more customers in each line:
snippet,
count (distinct customer_id) over (Partition by customer_id) as Customer_ID
,count (distinct customer_shipment_item_id) Over (Partition by customer_id) as customer_items
,count (distinct product_group) Over (Partition by customer_id) as customer_product_groups
Can you explain how this would work?
Try this. Unless I don't understand what you are looking for, you don't need the Partition By clause.
count (distinct customer_id) as Customer_ID
,count (distinct customer_shipment_item_id) as customer_items
,count (distinct product_group) as customer_product_groups
I think something like this would give you what you are looking for:
SELECT COUNT(customer_id) Customer_ID, customer_items, customer_product_groups
FROM
(SELECT customer_id, COUNT(DISTINCT customer_shipment_item_id) as customer_items,
COUNT(DISTINCT product_group) as customer_product_groups
FROM TABLENAME
JOIN <YOUR JOINS>
WHERE customer_id IN (SELECT customer_ID FROM <YOUR JOINS> WHERE customer_shipment_item_id = x)
GROUP BY customer_id
) a
GROUP BY customer_items, customer_product_groups