mysql fill in missing dates for each specific value in column - mysql

I am trying to count the number of events in the subchannel column of my l_events table between the dates 2013-10-01 and 2014-03-31 and group by specific subchannel, year and month.
Right now my results look like:
year month subchannel count(*)
2013 10 creativemornings 1
2014 3 creativemornings 2
2013 11 founderinstitute 1
I would like my results to include rows for each specific subchannel where no events occurred occurred in that month. So something like:
year month subchannel count(*)
2013 10 creativemornings 1
2013 11 creativemornings 0
2013 12 creativemornings 0
2014 1 creativemornings 0
2014 2 creativemornings 0
2014 3 creativemornings 2
2013 10 founderinstitute 0
2013 11 founderinstitute 1
2013 12 founderinstitute 0
2014 1 founderinstitute 0
2014 2 founderinstitute 0
2014 3 founderinstitute 0
I tried to join my query to my calendar table (which includes a datetime column of all relevent dates) but it didn't work. Any thoughts?
SELECT
year(l.created) as year,
month(l.created) as month,
l.subchannel,
count(*)
FROM db.l_events l
right JOIN db.calendar c
ON (date(l.created) = c.datefield)
WHERE
l.created between '2013-10-01' and '2014-03-31'
group by
l.subchannel,
year(l.created),
month(l.created)
;

This will do it. It creates a Cartesian product of your subchannel list and your calendar table and LEFT JOINs the l_events table to that result set.
SELECT
year(c.datefield) as year,
month(c.datefield) as month,
s.subchannel,
count(l.created)
FROM db.calendar c
CROSS JOIN (select distinct subchannel from l_events) s
LEFT JOIN db.l_events l
ON (date(l.created) = c.datefield)
AND l.subchannel = s.subchannel
Where c.datefield between '2013-10-01' and '2014-03-31'
group by
s.subchannel,
year(c.created),
month(.created)
order by
s.subchannel,
year(c.created),
month(.created)
;

Related

Can we group sum in previous period in SQL

I need to group sum in from previous period in SQL. Here's my data from simplified customer (customer A, B, and C)
Customer Year Month Order
A 2019 5 10
A 2019 4 5
A 2019 3 3
A 2019 2 1
A 2018 12 3
B 2019 5 1
B 2019 4 2
B 2019 3 1
C 2019 5 2
C 2019 4 1
C 2019 2 1
C 2019 1 3
Expected output is sum Order for previous period
For example, Expected output in first row is 12, because it sum in previous period (7 + 4 + 3 + 0) in customer A.
Another example, Expected output in second row is 7 because it sum in previous period (4 + 3 + 0) in customer A. So, table below is the expected output from table above
Customer Year Month Order Output
A 2019 5 10 12
A 2019 4 5 7
A 2019 3 3 4
A 2019 2 1 3
A 2018 12 3 0
B 2019 5 1 3
B 2019 4 2 1
B 2019 3 1 0
C 2019 5 2 5
C 2019 4 1 4
C 2019 2 1 3
C 2019 1 3 0
I need to do this in SQL
First of all, i would change the name of your columns (year, month and order are mysql reserved words or functions). You could do it with a subquery like this:
select customer,
`year`,
`month`,
`order`,
(select sum(output)
from yourtable b
where a.customer=b.customer and (a.year>b.year or (a.year=b.year and a.month>b.month)))
from yourtable a
What you do is you get every row and the last column is the sum of output for all other columns with the same customer and have year lower than the year in your customer or if the year is the same, the month is lower
In MySQL 8+, you should use window functions:
select t.*,
sum(output) over (partition by customer order by year, month)
from t;
Note only is this more concise, but it should have better performance as well.
This can be achieved by Window Functions. Below link provides the example
LAG([,offset[, default_value]]) OVER (
PARTITION BY expr,...
ORDER BY expr [ASC|DESC],...
)
http://www.mysqltutorial.org/mysql-window-functions/mysql-lag-function/

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

Employee Year Calculation

I have employees table with date_of_join field
and I have employee_leaves table with the following fields:
employee_id
leave_from
leave_to
total_days
the employee joined on 15 Feb 2011
I want to have a query showing the cound of leaves for every employee years based on his date_of_join
for example, if the employee joined on 15 Feb 2011 then the result will be like this:
Feb 2011 to feb 2012 ---- totals days: 21
Feb 2012 to feb 2013 ---- totals days: 26
Feb 2013 to feb 2014 ---- totals days: 8
where Feb to feb is the employee year so it's from 15 Feb to 14 Feb every year
can anyone help please?
Not having your data it is difficult to test this but I came up with the following based on your description:
SELECT employees.employee_id, DATE_ADD(employees.date_of_join, INTERVAL yrs.years) frm
,DATE_ADD(employees.date_of_join, INTERVAL yrs.years + 1) too,
SUM(employee_leaves.total_days)
FROM employee_leaves
INNER JOIN (SELECT 0 years UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) yrs
ON 1=1
INNER JOIN employees ON employee_leaves.employee_id = employees.employee_id
AND employee_leaves.leave_from BETWEEN DATE_ADD(employees.date_of_join, INTERVAL yrs.years) AND DATE_ADD(employees.date_of_join, INTERVAL yrs.years + 1)
GROUP BY employees.employee_id, DATE_ADD(employees.date_of_join, INTERVAL yrs.years)
;
Probably needs some fiddling, hope this helps.

I want to get total amount monthly with filled gaps,i mean 0 for months having no transactions

I have made a table 'saving' with columns ac_no,Transaction_id and amount.
Other table is just filled with random dates.
So far I have tried this query which i think is very close..
1)
select
sd.ac_no,year(sd.Transaction_date) as Transaction_year,month(sd.Transaction_date) as Transaction_month,
sum(sd.amount) as Total
from saving sd
left join other dt
on sd.Transaction_date = dt.Transaction_date
where sd.ac_no = 11 and sd.Transaction_date between '2014-01-01' and '2014-12-31'
group by year(sd.Transaction_date),month(sd.Transaction_date)
and I am getting this result:
AccountNumber Transaction_year Transaction_month Total
11 2014 3 5000
11 2014 7 1000
but I want result like this:
AccountNumber Transaction_year Transaction_month Total
11 2014 1 0
11 2014 2 0
11 2014 3 5000
11 2014 4 0
11 2014 5 0
11 2014 6 0
11 2014 7 1000
Please help and thanx in advance..

MySQL Query to group by date range

I am having a problem with this query:
SELECT
YEAR(passDate) as Year,
count(*) AS total_amount
FROM
`dsp_drop_pass_details`
WHERE passDate
BETWEEN '2009-01-01'
AND '2012-05-01'
AND batch='DROPOUT'
GROUP BY YEAR(passDate)
ORDER BY YEAR(passDate)
output---
Month total amount
2011 30
2012 20
But my desire out put is
Month total amount
2009 0
2010 0
2011 40
2012 20
I want 0 where count is 0
The easiest way would be to have a table Years, with all the wanted years.
create table Years(yearValue int);
insert into years values (2001), (2002)..., (2020);
then do a left join on your actual table.
SELECT y.yearValue, COALESCE(COUNT(d.id), 0) --assumning you have a field id in dsp_drop_pass_details
FROM years y
LEFT join dsp_drop_pass_details d on y.yearValue = YEAR(d.passDate)
WHERE y.yearValue between 2009 and 2012
GROUP BY y.yearValue
ORDER BY y.yearValue;