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
Related
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
)
I'm having trouble coming up with a query to get the number of customers who purchased on multiple dates.
We're given a table of product purchases. Each row in the table represents an individual user product purchase.if the customer purchased two things on the same day that does not count as an upsell as they were purchased within a similar timeframe.
'transactions' table:
column
type
id
integer
user_id
integer
created_at
datetime
product_id
integer
quantity
integer
I tried in this way
select count(*)
from
( select user_id
, count(date)
from
( SELECT user_id
, DATE(created_at) AS date
FROM transactions
GROUP BY 1,2
) S
group
by 1
having count(date)>1
) A
I think you want:
SELECT COUNT(*)
FROM
(
SELECT user_id
FROM transactions
GROUP BY user_id
HAVING COUNT(DISTINCT DATE(created_at)) > 1
) t;
The subquery finds all users having transacted on more than one date, the outer query finds the count of such users.
Count the distinct dates per user, first, then count from table when the count is > 1.
See below:
WITH T as (select user_id,
count(distinct DATE(created_at)) as count
from transactions
GROUP BY user_id)
select count(*) from T where count > 1
I have a PROJECTS table with PROJECT_ID, CUSTOMER_ID, COMPANY_ID and COST columns.
One customer could have one or several projects in different companies.
What I want is to choose a customer, who generates the smallest income for each company.
For example if the table looks like this
project_id customer_id company_id cost
1 1 1 1000
2 1 1 100
3 2 1 3000
4 1 2 300
5 2 2 100
, the expected answer is:
(COMPANY_ID) 1 | (CUSTOMER_ID) 1 | (COST) 1100
(COMPANY_ID) 2 | (CUSTOMER_ID) 2 | (COST) 100
Because the first customer generates 1000 + 100 = 1100 in total.
My query looks like this:
SELECT TABLE1.company_id, TABLE1.customer_id, MIN(profit)
FROM (
SELECT company_id, customer_id, SUM(projects.cost) AS profit
FROM projects
GROUP BY company_id,customer_id
) AS TABLE1
GROUP BY TABLE1.company_id;
It counts the MIN profit, but the ID's in CUSTOMER_ID column are always wrong. How can I build a connection between customers' IDs and their total profit for each company? Is it possible?
Thanks for helping.
One method for doing this is a "hack", because it uses string operations to get the value you want:
SELECT cc.company_id,
SUBSTRING_INDEX(GROUP_CONCAT(cc.customer_id ORDER BY profit ASC), ',', 1) as customer_id,
MIN(profit)
FROM (SELECT p.company_id, p.customer_id, SUM(p.cost) AS profit
FROM projects p
GROUP BY p.company_id, p.customer_id
) cc
GROUP BY cc.company_id;
An alternative in MySQL is something like this:
SELECT p.company_id, p.customer_id, SUM(p.cost) AS profit
FROM projects p
GROUP BY p.company_id, p.customer_id
HAVING SUM(p.cost) = (SELECT SUM(p2.cost)
FROM projects p2
WHERE p2.company_id = p.company_id
ORDER BY SUM(p2.cost) ASC
LIMIT 1
);
The two versions are subtly different:
The first will always return one customer, even if there are ties.
The first will convert the company_id to a string.
The first can run into overflow conditions, because the length of the intermediate result for group_concat() is controlled by a system parameter.
Use HAVING and ALL
SELECT p.company_id,
p.customer_id,
SUM(p.cost) AS profit
FROM projects p
GROUP BY p.company_id, p.customer_id
HAVING SUM(p.cost) <= ALL(
SELECT SUM(p2.cost)
FROM projects p2
WHERE p2.company_id = p.company_id
GROUP BY p2.customer_id
)
E.g.:
SELECT a.*
FROM
( SELECT customer_id
, company_id
, SUM(cost) total
FROM my_table
GROUP
BY customer_id
, company_id
) a
JOIN
( SELECT company_id
, MIN(total) min_total
FROM
( SELECT customer_id
, company_id
, SUM(cost) total
FROM my_table
GROUP
BY customer_id
, company_id
) x
GROUP
BY company_id
) b
ON b.company_id = a.company_id
AND b.min_total = a.total;
Given a table with a column for timestamps, I want to get the 10 most recent records with particular columns being unique.
How can this be done?
Example:
Data:
purchases
-----------------------------------------------------------------
timestamp first_name last_name customer_id product_name purchase_amount
How can I get the 5 most recent customers who made a purchase, and the product_name and purchase_amount?
Result:
James, Jackson, 1234, 'foo', 432.123
Tim, McTimothy, 321, 'bar', 5124.11
Bob, Bobbertson, 55, 'foo', 432.123
Claire, Rando, 191, 'tv', 700.00
Jimbo, Manman, 631, 'ps4', 450.00
What I've tried:
This query fails since it would require an aggregation on product_name and purchase_amount, but we don't want an aggregation, just the latest value.
SELECT first_name, last_name, customer_id, product_id
FROM purchases
GROUP BY first_name, last_name, customer_id
ORDER BY timestamp DESC
LIMIT 10
I think this will do it:
SELECT p.*
FROM
(
SELECT customer_id, MAX(timestamp) last_purchase_time
FROM purchases
GROUP BY customer_id
ORDER BY MAX(timestamp) DESC
LIMIT 5
) lp
INNER JOIN purchases p ON p.customer_id = lp.customer_id and p.timestamp = lp.last_purchase_time
The nested query gets the last purchase time for each customer, and further limits the nested result set to the 5 most recent customers. We then connect this back to the purchases table so we can see the full purchase data for the last purchase by each of those customers. This does make the assumption that a customer could not have two purchases at the exact same instance, but that's probably safe.
You could try adding a rank column that would act as an id, something like this:
SELECT first_name, last_name, customer_id, product_name
FROM
(SELECT first_name, last_name, customer_id, product_name, #rank := #rank + 1 AS rank
FROM purchases p1, (SELECT #rank := 0) r
ORDER BY timestamp DESC) p2
GROUP BY first_name, last_name, customer_id
LIMIT 10;
i'm assuming customer_id is unique. so we only need to use customer_id in
group clause
select * from purchases p2 where
concat(UNIX_TIMESTAMP((p2.timestamp)),'_',p2.customer_id)
in (
select concat(UNIX_TIMESTAMP(max(p.timestamp)),'_',p.customer_id)
from purchases p group by p.customer_id order by p.timestamp desc
) limit 10
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