SQL for different date data manipulation - mysql

Suppose I have two tables (Customers and Invoices). I want to know newest customers based on their first invoice date for x month. For example, a customer might have joined/registered in November but it is possible that he has placed his FIRST ORDER in January. So he is a new customer for my criteria.
Sample tables are given below:
DESIRED RESULTS:
Below is just one example for above sample data. C5 customer joined in August 2019 but he placed his first order in January 2020. So for me, he is a new customer.

If you want to filter on customers that have placed their first order after a given date, just use aggregation:
select customer, min(date) first_invoice_date
from invoices
group by customer
having first_invoice_date > #somedate
You can adapt (or remove) the having clause as needed.
If you want the details of the customer (eg its name and coutry), then you can join the customers table:
select c.*, o.first_invoice_date
from customers c
inner join (
select customer, min(date) first_invoice_date
from invoices
group by customer
having first_invoice_date > #somedate
) i on i.customer = c.id

Related

mySQL - How can I see which users submitted orders last month but not this month?

I need to figure out the users who submitted orders last month but not this month. This is my current query to count total users, but how can I cross check to see who has bought this month but not the last?
SELECT DISTINCT(customer_user_id)
FROM customer_orders
WHERE created_on > '2020-07-01'
This is my the customer orders table
this would be the expected output, a list of all the users
EDIT: Additionally, I'm trying to get a report of the users who submitted orders in July but not August, with their amount total for the month, number of orders, and user cellphone #. This is the query I'm using but its not giving me the result.
SELECT DISTINCT(co.customer_user_id), SUM(co.amount), COUNT(co.order_id), s.cellphone
FROM customer_orders co
JOIN subscribers s
ON co.customer_user_id = s.user_id
WHERE co.created_on > '2020-07-01'
AND month(co.created_on) <> month(curdate());
This is my subscriber table, and above is my customer orders table.
As I understood you want to filter the user's which are again created in current month. So,
-- not sure if you really need distinct
SELECT DISTINCT(c.customer_user_id)
FROM customer_orders c
WHERE c.created_on > '2020-07-01'
AND month(c.created_on) <> month(curdate());

SQL List data from table dependant on data from another table

I'm writing a CMS for a client who wishes for a sorting of his data by upcoming activities.
There is a table named customers which contains all of the customers, identified by the cust_id column.
There is also a table named activities, in which there is a cust_id column to pair it with a customer, and a date_last_done field to specify when the task was completed. The customer can have many activities to their record.
I want to fetch all customers where the most recent (date_last_done desc) activity was completed more than 11 months ago.
Here's my attempt:
SELECT
*
FROM
customers
INNER JOIN
activities
ON
activities.cust_id = customers.cust_id
WHERE
(SELECT
date_last_done
FROM
activities
WHERE
cust_id = ???
ORDER BY
date_last_done
DESC)
< date() - 11months
How would I edit my query to do this?
Join the customers table with a subquery that returns the customers with activity that fits the criteria.
SELECT c.*
FROM customers AS c
JOIN (SELECT cust_id
FROM activities
GROUP BY cust_id
HAVING MAX(date_last_done) < DATE_SUB(NOW(), INTERVAL 11 MONTH)) AS a
ON c.cust_id = a.cust_id

Left outer join in rails

I have two objects - Customers & Customer Checkins. Each customer has many checkins and each checkin belongs to one customer.
I need to come up with a query that outputs the complete list of customers together with their checkin count per month. My current query is shown below:
customer = Customer.where(account_id: 139).joins('LEFT JOIN
customer_checkins on customer_checkins.customer_id =
customers.id').uniq.select("COUNT(*) as count, customers.created_at as
created_at, customers.name, customers.telephone, customers.mobile,
customers.email, customers.gender, customers.city,
customers.birthday,date_format(customer_checkins.created_at, '%b') as
'month', customers.id").group("customer_checkins.customer_id,
date_format(customer_checkins.created_at, '%b %Y')")
This query does not list all the customers. What is wrong with my code?
It does not list all the customers because you're only searching for ones with account_id: 139.
Replace
customer = Customer.where(account_id: 139)...
With
customer = Customer...

Outputting customers who haven't repeat ordered since a specific date range in MySQL

I have searched around but have not found anything which seems to be totally relevant so I'm asking for some help.
I have a single table which contains orders, people can have multiple orders. I need to be able to select people who purchased in 2 years ago (April 2012) where they haven't purchased since, to identify unique people I am using email address as there is no unique customer ID. Here is the order table fields:
orderid,order date,name,email
I have limited SQL knowledge, but my approach previously has been to output a table of orders from April 2012 and another table from May 2012 to the present date. I then compare the 2 tables to find customers who haven't ordered since.
I can't help but feel like there is a more efficient way to do this in one query. Can anyone help?
Thanks,
Sam.
I would use LEFT JOIN here:
SELECT DISTINCT order1.email
FROM `order` order1
LEFT JOIN (SELECT email FROM `order` WHERE orderdate >= '2012-05-01') order2
ON order1.email = order2.email
WHERE orderdate < '2012-05-01'
AND order2.email IS NULL;
The main query is checking for people who ordered before May 2012, and the LEFT JOIN query is checking (with order2.email IS NULL) for people who have NOT ordered since then.
You can write this query without any join something like this:-
select email
from order
where email not in (select email from order where order_date >"April 2012")
and order_date < "April 2012";
Here, first condition filter outs all customer who have bought in last two years, and from second condition you get the customers who have bought two years ago.
As suggested, query with NOT EXISTS will go like this:
select o1.email
from order o1
where not exists (select 1 from order o2 where o2.order_date > "April 2012" and o1.email = o2.email)
and o1.order_date < "April 2012";

Query to find how many purchases were made this year, For each Artist

I need to list the Artist's Id_no, last name (lname) and how any purchases have been made on their releases this year. The only information about the purchases is different purchase dates.
My code so far :
SELECT id_no, lname, purchasedate AS num_ops
FROM Artist JOIN Sales ON Artist.id_no = Sales.artist
WHERE DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= purchasedate
However this only returns the Id_no's who have made sales, and I need all even if it is 0. On distrinctl name, and num_ops is a date of their first purchasedate. I need to alter this code to list how many purchases they have been involved in within this year. I've tried using COUNT(purchasedate) however this just returns one row. I wish the returning table to return:
1st Column: The Artist's ID Number
2nd Column: The Aritist's Last Name
3rd Column: The number of people who have purchased their CD's (which is a count of purchasedate)
I am struggling with the 3rd column majorly, and any help would be greatly appriciated.
You need:
a left join
to move the date condition into the ON clause of the JOIN
use the count(*) aggregating function
Like this:
SELECT id_no, lname, count(purchasedate) as num_ops
FROM Artist
LEFT JOIN Sales ON Artist.id_no = Sales.artist
AND DATE_SUB(CURDATE(),INTERVAL 1 YEAR) <= purchasedate
GROUP BY id_no, lname
The LEFT JOIN will ensure a row is returned for every artist even if there are no sales
By moving the date condition into the join that will still return a row for every artist even if there's no sale for the year. If the condition is left in the WHERE clause, that would filter out artists that didn't make sales in the last year.
A key point here is that the join condition may contain conditions unrelated to the keys involved - that's how you get conditional joins, which is what you want here to make the left join still function correctly