complicated column calculation in mysql to get a count of monthly visits - mysql

I have a two tables that look like this
customer table
first last cust_id
John Doe 0
Jane Doe 1
ledger table
posted_date cust_id
2014-01-14 0
2014-01-20 0
2013-12-20 0
2013-12-20 1
2013-11-12 1
2013-11-10 1
I need to calculate the number of months where the customer posted a transaction at least once, this is being called CustomerMonths for the last 12 months. This means CustomerMonths for each cust_id would be between 0 and 12. So for this data I would want to see
cust_id CustomerMonths
0 2
1 2
This is because cust_id 0 was in at least once in Jan 2014 and at least once in Dec 2013.
Similarly, cust_id 1 was in at least once in Dec 2013 and at least once in Nov 2013.
For this example for cust_id 0:
2014-01-14,
2014-01-20 = 1 CustomerMonths
2013-12-20 = 1 CustomerMonths
so total CustomerMonths for last 12 months for cust_id 0 is 2.
I have this working for one month but not sure how to get this to work for the last 12 months. Although I'd settle for it working for the last two months. I think i could figure out the rest. Here's what I have.
select distinct
c.cust_id,
(case when count(lJan.posted_date) = 0 then 0 else
case when count(lJan.posted_date) > 0 then 1 end end) as CustomerMonths
from 'customer' c
left join 'ledger' lJan on (lJan.cust_id = c.cust_id and lJan.posted_date between '2014-01-01' and '2014-01-31')
group by c.cust_id

You need to count distinct months, so use count(distinct). The question is what is the argument. Try this:
select c.cust_id,
count(distinct year(l.posted_date) * 100 + month(l.posted_date)) as CustomerMonths
from customer c left join
ledger l
on l.cust_id = c.cust_id and
l.posted_date between '2013-01-01' and '2014-01-31'
group by c.cust_id;
Another way of writing the select:
select c.cust_id,
count(distinct date_format(l.posted_date, '%Y-%m')) as CustomerMonths

Related

how to display months as columns along with min bal in MySQL

For example
ID TID DATE BALANCE
1 24 02-11-2018 198
2 2 08-11-2018 199
2 3 05-11-2018 0
4 13 26-11-2018 115
4 14 28-11-2018 113
Balance for Nov-18 should be displayed as below
ID BALANCE
1 198
2 0
3 0
4 113
for id-3, 0 should be displayed since there is no balance for these id in the month of November for id -1,2 & 4 min balance should be displayed.
Most of what you want can be obtained by a simple GROUP BY and some date formatting:
select a.id,
date_format(date, '%Y-%m') as month,
coalesce(min(balance), 0) as min_balance
from accounts a
left outer join balances b
on b.id = a.id
group by a.id, date_format(date, '%Y-%m')
order by a.id, date_format(date, '%Y-%m')
Here we're using the date_format function to extract the year and month from the date value, and then grouping the results by id and the formatted date. This produces the result
id month min_balance
1 2018-11 198
2 2018-11 0
3 0
4 2018-11 113
It seems apparent that there must be another table which contains all the account values, so I added a table named accounts with these values. Change this if needed.
db<>fiddle here

repeat customer count month wise in mysql

I'm loking for one logic that might be not accepatable.
But my requirement is I want count of customers(NewCustomers, repeatCustomers) on the basis of previous and current month
Like from this data I want
DATE NAME
2016-01-01 A
2016-01-01 B
2016-01-01 C
2016-01-05 E
2016-01-05 F
2016-01-25 G
2016-01-25 H
2016-02-25 A
2016-02-25 E
2016-02-10 X
2016-02-11 Y
2016-02-13 F
Output like this
MONTH NewCustomer RepeatCustomer CustomerCount of refernece month (Like here is JAN)
FEB 2 3 7
Same will go for next months
Any suggestion ? Thanks !!
I don't know what the reference month is, but you can get the first two columns by combining the first time you see a customer with who visits in each month:
select date_format(c.date, '%Y-%m') as yyyymm,
count(distinct c.name) as NumCustomers,
sum(case when date_format(c.date, '%Y-%m') <> date_format(cc.start_date, '%Y-%m')
then 1 else 0
end) as NumRepeatCustomers
from customers c join
(select c.name, min(c.date) as start_date
from customers c
group by c.name
) cc
on c.name = cc.name
group by date_format(c.date, '%Y-%m')
order by yyyymm;

MySQL Query for count of same column separately based on condition

We have an order table with fields as below e.g.
Timestamp PaymentID OrderID
341231231 6 1
342131231 12 2
123123123 18 3
123123122 14 4
123123143 12 5
433453454 6 6
445456456 18 7
What we want to do is get an output which will give us a month wise report on order count for each Payment Type but the payments are to be clubbed together for e.g. 6,8 PaymentID comes under type C so the count should be added for both in one
and all other PaymentID's come under type P
So the output what we want is like below.
Year Month C_Orders P_Orders
2015 01 0 4
2015 02 4 3
2015 03 1 0
2015 04 2 1
We tried 2 queries but has incorrect outputs
select SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),1,4) as year,SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),6,2) as month, co.payment_id, count(co.payment_id) as c_orders,co1.payment_id, count(co1.payment_id) as p_orders from
orders as co, orders as co1
WHERE co.payment_id in (6,18)
AND co1.payment_id not in (6,18)
GROUP BY year,month
AND
select SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),1,4) as year,SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),6,2) as month, 'COD', count(co.payment_id) as cod_orders
from
orders as co
WHERE co.timestamp >= UNIX_TIMESTAMP(CONVERT_TZ('2014-01-01 00:00:00','+00:00','+5:30')) AND co.timestamp <= UNIX_TIMESTAMP(CONVERT_TZ('2020-12-31 23:59:59','+00:00','+5:30')) AND co.is_parent_order = 'N' AND co.status IN ('C','G','E','P') AND co.payment_id in (6,18)
GROUP BY year,month
union
select SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),1,4) as year,SUBSTRING(CONVERT_TZ(FROM_UNIXTIME(co.timestamp),'+00:00','+5:30'),6,2) as month, 'PREPAID', count(co.payment_id) as prepaid_orders
from
orders as co
WHERE co.timestamp >= UNIX_TIMESTAMP(CONVERT_TZ('2014-01-01 00:00:00','+00:00','+5:30')) AND co.timestamp <= UNIX_TIMESTAMP(CONVERT_TZ('2020-12-31 23:59:59','+00:00','+5:30')) AND co.is_parent_order = 'N' AND co.status IN ('C','G','E','P') AND co.payment_id not in (6,18)
GROUP BY year,month
Use a case statement to only sum/count the values when a condition is met.
select year, month,
sum(case when payment_id in (6,18) then 1 else 0 end) as 'payment_id in (6,18)',
count(case when payment_id not in (6,18) then payment_id else null end) as 'payment_id not in (6,18)'
from table
group by 1,2

Trying to see how many orders by year/month for customers based on itemised list of orders

I have a simple database table listing customerID and orderDate. I would like to produce a grid showing how many orders each customer has placed month between a date range
e.g.
customerID orderDate
1 2015-01-15
1 2015-01-25
1 2015-02-01
1 2015-04-05
2 2015-02-15
2 2015-02-25
2 2015-03-01
2 2015-03-05
3 2015-02-01
3 2015-05-08
And then what I am looking for is:
customerID jan2015 feb2015 mar2015 apr2015 may2015
1 2 1 0 1 0
2 0 2 2 0 0
3 0 1 0 0 1
You can use conditional aggregation for this. MySQL has several helpful date and time functions which you can use for queries like this. In this example, I would take note of the YEAR() and MONTH() functions. Then you can write conditional statements for each column the count the rows that occur in each month and year, like this:
SELECT customer,
SUM(MONTH(orderDate) = 1 AND YEAR(orderDate) = 2015) AS jan2015,
SUM(MONTH(orderDate) = 2 AND YEAR(orderDate) = 2015) AS feb2015,
SUM(MONTH(orderDate) = 3 AND YEAR(orderDate) = 2015) AS mar2015,
SUM(MONTH(orderDate) = 4 AND YEAR(orderDate) = 2015) AS apr2015,
SUM(MONTH(orderDate) = 5 AND YEAR(orderDate) = 2015) AS may2015
FROM orders
GROUP BY customer;
Here is an SQL Fiddle example.

showing one column several times with data from 3 different date intervals

I am trying to show three different figures of the same column In a mysql query and joining all three tables, I would like to keep one month static: April, so it would be a case like this I want to show The current month, the previous month and the static month of the year I'm working with, in this case let us stick with 2012
table: persons
ID name
1 Carl
table: vehicle
ID v_name person_veh
100 Dodge Viper 1
Table:payment
pay_id , pay_date, amount person_id
1 2012-02-12 1000 1
2 2012-03-11 780 1
3 2012-04-15 890 1
4 2012-05-12 1200 1
5 2012-06-12 1890 1
6 2012-07-12 1350 1
7 2012-08-12 1450 1
So what I want to do is show the column amount for the month of April as I said I want to keep that row static: 890, the current month lets say the current month is August:1450 and the previous month amount which would be July:1350: so the final result would be something like this:
name v_name april_amount current_month_amount previous_month_amount
Carl Dodge viper 890 1450 1350
You can use the following - which uses an aggregate function with a CASE statement:
select p.name,
v.v_name,
sum(case when Month(py.pay_date) = 4 then amount end) april_amount,
sum(case when Month(py.pay_date) = Month(curdate())
then amount end) current_month_amount,
sum(case when Month(py.pay_date) = Month(curdate())-1
then amount end) previous_month_amount
from persons p
left join vehicle v
on p.id = v.person_veh
left join payment py
on p.id = py.person_id
group by p.name,
v.v_name
see SQL Fiddle with Demo
Try
SELECT a.name, b.pay_date, b.amount, b.person_id, c.v_name
FROM persons a
LEFT JOIN payment b on a.id = b.person_id
LEFT JOIN vehicle c on a.id = c.person_veh
This query assumes id, person_veh and person_id are the like columns which links this user across these three tables