Replacing a union in MySQL - 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

Related

Distinct after grouping by

I have below query as
WITH search_agg as(
SELECT user_id, count(search_id) as count_search
FROM search
WHERE date>current_date -interval '7 days'
GROUP BY user_id
HAVING count_search>10)
SELECT count (distinct user_id)
FROM search_agg
If am correct, I don't need distinct in my outer query since my group by takes care of that correct? or is it better practice to have distinct anyway? Thanks
It depends upon your need in this case there is no need for distinct. Because CTE already returns (distinct) group by user_id.
WITH search_agg as(
SELECT user_id, count(search_id) as count_search
FROM search
WHERE date>current_date -interval '7 days'
GROUP BY user_id
HAVING count_search>10)
SELECT count (user_id)
FROM search_agg;
If you have group by based on two or more columns then you need to use distinct to fetch unique rows.

how to sum two columns from different tables MySQL

I need to sum the data from two different columns located in different tables and grouped by session_id.....
I need to sum the column of spent_points + price_points grouped by session_id
this is the result i hope to get
I have tried with this query but I have only managed to group the data but I have not been able to sum it by session_id
SELECT session_details.session_id,SUM(session_details.spent_points) AS total_sum_session FROM session_details WHERE session_details.session_id IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy") GROUP BY session_details.session_id UNION SELECT template_sales.session_id, SUM(template_sales.price_points) AS total_sum_sales FROM template_sales WHERE template_sales.session_id IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy") GROUP BY template_sales.session_id
First use UNION ALL to get all the rows from the 2 tables that you want and then aggregate:
SELECT session_id, SUM(points) AS total_points
FROM (
SELECT session_id, spent_points AS points
FROM session_details
WHERE session_id IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy")
UNION ALL
SELECT session_id, price_points
FROM template_sales
WHERE session_id IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy")
) t
GROUP BY session_id
You're almost there:
WITH union_rows (session_id, points) AS (
SELECT session_details.session_id, session_details.spent_points
FROM session_details
WHERE session_details.session_id IN ('-Meagevy6y9ukbmFXvB7','-Meak6dG9iqvHWfAGQvy')
UNION ALL
SELECT template_sales.session_id, template_sales.price_points
FROM template_sales
WHERE template_sales.session_id IN ('-Meagevy6y9ukbmFXvB7','-Meak6dG9iqvHWfAGQvy')
)
SELECT session_id
, SUM(points) AS total_sum
FROM union_rows
GROUP BY session_id
;
If you have an older version of MySQL, without WITH clause support, use a derived table instead.
The session_id filter can be done outside the CTE term, but then you may carry all those other rows as well, until the filter is processed.
Maybe you can do a JOIN between this two tables using the session_id.
After that you can sum the two attributes.
It'll be something like this:
SELECT session_details.session_id,SUM(SD.SPENT_POINTS + TSS.PRICE_POINTS ) AS total_sum_session
FROM session_details SD
JOIN template_sales.session_id TSS ON SD.SESSION_ID = TSS.SESSION_ID
WHERE SD.session_id IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy")
GROUP BY SD.session_id
Try this:
SELECT A.session_id,SUM(A.Total) AS Total
FROM
(
SELECT session_details.session_id,session_details.spent_points AS Total
FROM session_details
WHERE session_details.session_id IN ("-Meagevy6y9ukbmFXvB7","-
Meak6dG9iqvHWfAGQvy")
UNION ALL
SELECT template_sales.session_id, template_sales.price_points AS Total
FROM template_sales
WHERE template_sales.session_id
IN ("-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy")
) AS A
GROUP BY A.session_id

SQL query to get the number of customers who purchased on multiple dates

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

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;

Find the greatest value among four tables in mysql

I have a column Date with the same name in four tables Products, Customers, Shops, World in mysql. what i want to do is that i want to find the greatest date in the DATE COLUMN of all four tables. I don't want the greatest date of every table but the greatest one in all four tables. I hope you are understanding. Please help me
The most efficient way I can think of would be using the greatest function:
select greatest(
(select max(date) from products),
(select max(date) from customers),
(select max(date) from shops),
(select max(date) from world)
) greatest_date
SQLFiddle demo
This might work:
SELECT MAX(Date) as Max_Date
FROM (
SELECT Date FROM Products
UNION
SELECT Date FROM Customers
UNION
SELECT Date FROM Shops
UNION
SELECT Date FROM World
) AS P;