Total orders by new customers Each day and week - mysql

I'm fairly new to SQL and I'm trying get total orders by new customers every day and each week in Mysql ( feel free to answer in any sql versions). First I tried to get total orders by new customers every day by writing below query, however Im getting incorrect results.
select COUNT(u.orderId), date(u.createdAt) as ord_dt, u.userId
from userorder u
inner join
(
select userId, min(date(createdAt)) as first_date
from userorder
group by 1
) g
on g.userId = u.userId
where g.first_date < date(u.createdAt)
group by 3
Link to the dataset https://docs.google.com/spreadsheets/d/1fA6hAkDJgp28BF0G0aSe9Ml64S9cIwch/edit?usp=sharing&ouid=104686423957654811582&rtpof=true&sd=true
Any help is appreciated

I wrote this query to get the daily answer.
select first_order_date, sum(first_total_order) as tot from
(select user_id,min(order_date) as first_order_date,total_order as
first_total_order
from
(select userId as user_id,date(createdAt) as order_date,count(orderId)
as total_order
from userorder
group by 1,2
) as uo
group by 1) z
group by 1;

Related

MySQL update in a multiple join statement with only highest value from third table

(I know this could have been solved by redesigning the database, but I have already spent a lot of time researching my problem and I am hoping to learn a solution which can also be useful for later..)
I have a registration system. Users who are participants of a certain activity will be placed in the registration-table, which will be linked to the activity table, which will be linked to the weeks table, and I need to anonymize (UPDATE) the name in the users-table when the last activity the user participated in is more than four weeks old.
My table is this:
USERS
id, name
REGISTRATION
uid, aid (uid = USERS.id, aid = ACTIVITY.id)
ACTIVITY
wid (wid = WEEKS.id)
WEEKS
year, weeknumber
My quest is to find all USERS.id who has'nt been registered for an activity which for 4 weeks, and I which to anonymize (UPDATE) the USERS.name field in that case. So I need to select all users and through the registration-table find the activity with the latest WEEKS.year + WEEKS.weeknumber and then determine if that entry is more than 4 weeks old.
I believe I have been able to solve this as a SELECT, with the following statement:
SELECT u.id, r.act_id, a.wid, w.weeknumber, w.year
FROM users AS u
INNER JOIN registration AS r ON r.uid = u.id
INNER JOIN activity AS a ON a.id = r.aid
INNER JOIN weeks AS w ON w.id = (
SELECT id
FROM weeks AS w2
WHERE w2.id = a.wid
ORDER BY year DESC, weeknumber DESC
LIMIT 1
)
WHERE w.year=YEAR(NOW())
AND w.weeknumber=WEEK(NOW())-5
GROUP BY u.id
ORDER BY u.id DESC
However I am having problem converting this to a functional UPDATE-statement. What I have so far doesn't seem to get the latest entry from the weeks-table:
UPDATE users u
JOIN registration AS r ON r.uid = u.id
JOIN activity AS a ON a.id = r.aid
JOIN weeks AS w ON w.id = (
SELECT id
FROM weeks AS w2
WHERE w2.id = a.wid
ORDER BY year DESC, weeknumber DESC
LIMIT 1
)
SET u.name = 'Anonymized'
WHERE w.year=YEAR(NOW())
AND w.weeknumber=WEEK(NOW())-5
I would be very grateful for any pointers in the right direction as my head is spinning at this point.

SQL How to find which customer has rented the most films?

I'm struggling with a question that said Which customer has rented the
most films?
I am doing this using the Seikila sample database in MySQL. I have something that joins my tables together and attempts to give me a count but I know its wrong just looking at the actual data in the rental table.
my code is as below
SELECT r.rental_id, cust.customer_id, count(*) as Total_Rentals
FROM rental as r
INNER JOIN customer AS cust on r.customer_id = cust.customer_id
GROUP BY cust.customer_id;
but it tells me for example customer 1 has rented 32 movies, which I know is wrong. what am I doing wrong?
since I was asked for clarification, the database I am using is:
https://dev.mysql.com/doc/sakila/en/
And I am trying to find which customer has rented the most films, I am not entirely sure what my script is actually returning.
Remove the column rental_id from the select list and sort the result by count(*) descending to return the top 1 row:
SELECT cust.customer_id, cust.name, count(*) as Total_Rentals
FROM rental as r
INNER JOIN customer AS cust on r.customer_id = cust.customer_id
GROUP BY cust.customer_id, cust.name
ORDER BY Total_Rentals DESC LIMIT 1
But if you only need the customer's id then there is no need for a join:
SELECT customer_id, count(*) as Total_Rentals
FROM rental
GROUP BY customer_id
ORDER BY Total_Rentals DESC LIMIT 1
You need to join customer and rental, group by customer id (without rental id) and count it:
SELECT cust.customer_id, count(*) as Total_Rentals
FROM rental as r
INNER JOIN customer AS cust on r.customer_id = cust.customer_id
GROUP BY cust.customer_id;
So this code should work. If it doesn't work, that probably means that you have duplicates or other nonconventional issues.

Return 0 counts in GROUP BY with multiple columns in SQL

I have a MySQL script that the returns the count of new users per week by city. The problem is it omits any city that doesn't have users in a week. I need it to return 0 when there were no users that week.
select
FROM_DAYS(TO_DAYS([u.created_at:pst]) - MOD(TO_DAYS([u.created_at:pst]) -1, 7)) as week,
a.city,
count(u.id) as this_week_signups_to_date
from users u
left join addresses a on a.user_id = u.id
group by
week, city
order by
week DESC
Any ideas how I can do this?
Maybe it's not the smoothest solution, but you could use a cross join operation like this:
select week,
case when joined.city = all_cities.city then this_week_signups_to_date else 0 end
as this_week_signups_to_date,
all_cities.city
from
(select
week([u.created_at:pst]) as week, --you could use week() in mysql or datepart() in t-sql
a.city,
count(u.id) as this_week_signups_to_date
from users u
left join addresses a on a.user_id = u.id --left/right join depends on your needs
group by week, city) joined
cross join
(select distinct city from addresses) all_cities
order by week desc

Average days between first and second purchase

can someone assist with the following. I need to figure out what the average day difference is between the first and second purchase of a customer:
I have the below: can someone assist with with my query please.
SELECT src.id, AVG(DATEDIFF(dest.purchasing, src.registrations)) AS avgdays FROM
(SELECT accounts.id, accounts.`created_date` AS registrations FROM accounts
WHERE YEAR(accounts.`created_date`) =2018 AND MONTH(accounts.`created_date`) =4) src
INNER JOIN
(SELECT account_id, MIN(created_date) AS purchasing
FROM ordering
WHERE STATUS = 'Fulfilled'
GROUP BY account_id
) dest
ON
dest.account_id = src.id;
The below query will give you the average difference between 2nd purchase if customer registration date is also his first order purchase date.
select account_id,customer_created,
avg(DATEDIFF(order_created, customer_created)) from
(select a.account_id,b.created_at as order_created, a.created_at
customer_created from
(select * from accounts where YEAR(created_at) =2018 AND
MONTH(created_at) =4) a
INNER JOIN ordering b on a.account_id=b.account_id where
b.status="Delivered" ) a
where customer_created <> order_created GROUP BY a.account_id ;

mysql getting all not exists from 2 tables

Hi I've got 2 tables:
customers
invoices
I'd like to find all customers who hasn't bought from me monthly for the past 6 months. This is what I've got at the moment:
SELECT * FROM customers WHERE NOT EXISTS (SELECT * FROM invoices WHERE invoices.customerid = customers.customerid AND month(invoices.fdate) = '2')
it kept running for 10 mins and there are still no results. i'm thinking that even if my syntax works, i'd have to go about it monthly, and crossing it off my customers table manually.
is there a better solution? all help appreciated. Thanks
You query doesn't quite do what you want. The correctly phrased one probably won't work any better:
SELECT c.*
FROM customers c
WHERE NOT EXISTS (SELECT 1
FROM invoices i
WHERE i.customerid = c.customerid AND
i.fdate >= CURDATE() - interval 6 month
);
For this version, you want an index on invoices(customerid, fdate).
You might also give this a shot:
SELECT c.*
FROM customers c JOIN
(SELECT customerid, MAX(fdate) as max_fdate
FROM invoices i
GROUP BY customerid
) i
ON i.customerid = c.customerid
WHERE i.max_fdate < CURDATE() - interval 6 month;