One-to-many query with subtoals and limits - mysql

Requirements: Select customers with 5 or more invoices totaling more than $3000 with transactions from Sept 2011 to current date.
DBMS: MySQL 5.6
Tables:
customers: customerID (...)
invoice: customerID,invoice_no,order_date,order_total (...)
I wrote several MySQL queries. The one that comes "closest" to working appears below. The problem with the results is twofold:
It looks at the total of all invoices per custopmer, not just those within the date range.
It pulls in some (but not all) records that are outside of the date range.
Here is the query:
#Customers with 5 or more invoices Totaling more than $3000 From Sept 2011 to current
SELECT distinct c2.customerID,c2.firstname,c2.lastname,c2.company,c2.address,c2.address2,c2.city,c2.state,c2.country,c2.phone,c2.email,SUM(c1.order_total)
FROM
customers c2 LEFT JOIN invoice c1
ON c2.customerID = c1.customerID
AND ((date(c1.order_date)) between '2011-09-01' and date(now()))
GROUP BY
c1.customerID
HAVING
COUNT(c1.invoice_no)>=7 and sum(c1.order_total) >=3000
Any help would be appreciated greatly.
Thanks.

This should do it:
select c.*, SUM(i.order_total) total, COUNT(*) order_count
FROM customers c
JOIN invoice i ON c.customerID = i.customerID
WHERE i.order_date >= '2011-09-01'
GROUP BY c.customerID
HAVING order_count >= 5 and total > 3000

Related

SQL count and sum issue

I have 2 tables with data.
The first table cus contains the customer data. The second table invoice contains the invoices created by the customer.
I want to select the total created invoices and the total sum of the invoices per customer.
Here is what I have:
SELECT cus.cus_id, cus.name_cus, count(invoice.id) as id2, CONCAT('€ ', ROUND(SUM(invoice.total),2)) as total, cus.id
FROM cus
LEFT OUTER JOIN invoice ON cus.cus_id = invoice.cus_id
WHERE cus.user_id='2'
GROUP BY cus.cus_id
To test this I have added some data to my database. The first customer has 2 invoices with a total sum of 100 (50+50).
The second customer has 3 invoices with a total sum of 30 (10+10+10).
But the SQL code dont shows me these results.
The response is for customer 1: total invoices = 1, total = 50
The response is for customer 1: total invoices = 0, total = (empty)
Does someone know what is wrong with my SQL statement?
The database type I am using is MySQL.
Here is a sample: http://sqlfiddle.com/#!9/a9f9f/1
Try grouping up your invoice count and sum as a subquery first, like:
SELECT cus.cus_id, cus.name_cus, inv.invoice_count, inv.invoice_total, cus.id
FROM cus
LEFT OUTER JOIN
(
SELECT inv.cus_id,
COUNT(inv.id) AS invoice_count,
CONCAT('€ ', ROUND(SUM(inv.total),2)) AS invoice_total
FROM invoice inv
GROUP BY inv.cus_id
) inv
ON cus.cus_id = inv.cus_id
WHERE cus.user_id='2'
If you're using SQL Server then your query should be like this --
SELECT C.cus_id
,C.name_cus
,Count(I.id) AS NumberOfInvoices
,IsNull(Sum(I.Price), 0) AS TotalPrice
FROM Customer C
LEFT JOIN Invoice I ON C.cus_id = I.cus_id
GROUP BY C.cus_id, C.name_cus
ORDER BY C.cus_id;
This is a simple sql Query as i understood your problem. I assumed CustomerID is in both tables. I think this Query will help you.
select i.CustomerID,i.CustomerName,COUNT(i.InvoiceID) as A, SUM(i.invoicetotal) as b
from Cus c,Invoice i
where i.CustomerID=c.CustomerID
group by i.CustomerID

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;

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

MySQL query help (join, subselect)

I have 2 tables: orders and bookings.
The orders table contain unique orders from customers. Each customer has booked a locker for a period of 1 to 5 years and therefore the bookings table can contain 1 to 5 rows pr. order (1 row for each year). Each row in the booking table contains and end_date which is the same date every year (20XX-06-30).
I want to select all the orders where the corresponding final end_date in the bookings table is this year (2014-06-30).
SELECT DISTINCT orders.id
FROM orders,
bookings
WHERE orders.id = bookings.order_id
AND bookings.end_date = '2014-06-30'
The problem with this query is that it also selects the orders where the end_date in the booking rows continue the following years (2015-06-30, 2016-06-30 etc).
I am not sure I understood well, but here's a solution for what I understood, this should get you the order ids where there last end date (max) is 2014-06-30.
SELECT orders.id, MAX(bookings.end_date)
FROM orders INNER JOIN bookings
ON orders.id = bookings.order_id
GROUP BY bookings.order_id
HAVING MAX(bookings.end_date) = '2014-06-30'
Maybe join to the bookings again, checking for a larger booking date for the same order id:-
SELECT orders.id
FROM orders
INNER JOIN bookings ON orders.id = bookings.order_id
LEFT OUTER JOIN bookings2 ON orders.id = bookings2.order_id AND bookings2.end_date > bookings.end_date
WHERE bookings.end_date = '2014-06-30'
AND bookings2.end_date IS NULL

JOIN & List Last Records per an ID

There are two tables:
SELECT id,customer FROM records;
SELECT user_id,call_date FROM call_history
Matching columns are:
records.id = call_history.user_id
The call_history table has call logs for customers.
There can be one or more call_history rows per customer.
I need to find when they called last time (for each customer).
For ex. userid=1 called twice, June 16 and July 20. Result must give me July 20, but I need to do the same for all customers from records table.
That is what I tried but it didn't work:
SELECT a.id, FROM_UNIXTIME(b.call_date,'%d/%m/%Y %H:%i') AS lastcall
FROM records a
INNER JOIN call_history b ON a.id=b.user_id
GROUP BY a.id ORDER BY b.call_date DESC;
Thank you.
Does this meet your requirements?
SELECT
r.id,
r.customer,
MAX(ch.call_date) AS lastcall
FROM
records AS r
INNER JOIN
call_history AS ch ON ch.user_id = r.id
GROUP BY
r.id,
r.customer