MySQL - How to populate weekly data in a month - mysql

How to select data from following table group by weeks in a month
Date Project Value Week
+----------+--------------+-------+------+
2018-11-07 A 2 45
2018-11-08 B 4 45
2018-11-09 C 3 45
2018-11-12 B 6 46
2018-11-13 A 5 46
2018-11-14 C 6 46
(First week is end on sunday or week number in a month)
So my result should look like this.
Project 1st Week 2nd Week 3rd Week 4th Week 5th Week
+----------+--------+--------+--------+--------+--------
A 0 2 5 0 0
B 0 4 6 0 0
C 0 3 6 0 0
I try this one :
SELECT project, value, week, date
FROM module_progress
WHERE
created_at BETWEEN '2018-11-01 00:00:00' AND '2018-11-31
AND date > DATE_SUB(NOW(), INTERVAL 1 WEEK) 23:59:59'
GROUP BY week
Thank you

Just use a sub query to get first week no for the month, and sum case statements for each week:
select year(date) as y, month(date) as m, project,
sum(case when week=w0 then value else 0 end) as w1,
sum(case when week=w0+1 then value else 0 end) as w2,
sum(case when week=w0+2 then value else 0 end) as w3,
sum(case when week=w0+3 then value else 0 end) as w4,
sum(case when week=w0+4 then value else 0 end) as w5
from #date d
join (select year(date) as y, month(date) as m, min(week) as w0 from #date group by year(date), month(date))
as d0 on d0.y=year(date) and d0.m=month(date)
group by year(date), month(date), project

Related

SQL how to aggregate by date and multiple criteria

I have this table:
id
amount
method
date
01
10
A
2022-01-24 12:27:14.440
02
80
A
2022-01-24 12:27:14.440
01
20
D
2022-02-24 12:27:14.440
01
10
D
2022-02-24 12:27:14.440
02
20
D
2022-02-24 12:27:14.440
03
30
D
2022-02-24 12:27:14.440
and I want this:
method
amount_sum_jan
n_transaction_jan
n_customer_jan
amount_sum_feb
n_transaction_feb
n_customer_feb
A
10
2
2
0
0
0
D
0
0
0
80
4
3
This is a table with 7 column and rows equal to the number of methods.
AMOUNT: sum of amount in one month of one method
N_TRANSACTIONS: number of transaction in one month with one method
N_CUSTOMER: number of customers (id) who used that method in one month
Can I get it with just one query?
You want to aggregate your data by method and have separate columns for January data and February data. You get this with conditional aggregation (CASE expression inside the aggregate function),
select
method,
sum(case when month(date) = 1 then amount else 0 end) as amount_sum_jan,
count(case when month(date) = 1 then 1 end) as n_transaction_jan,
count(distinct case when month(date) = 1 then id end) as n_customer_jan,
sum(case when month(date) = 2 then amount else 0 end) as amount_sum_feb,
count(case when month(date) = 2 then 1 end) as n_transaction_feb,
count(distinct case when month(date) = 2 then id end) as n_customer_feb
from mytable
group by method
order by method;
It is called pivot, and would for fix dates look like this.
An aggregation of the method for the year and month, and you can COUNT or SUM your number
select
`method`,
SUM(CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202201' then `amount` ELSE 0 END) amount_sum_jan,
SUM(CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202201' then 1 ELSE 0 END) n_transaction_jan,
COUNT(DISTINCT CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202201' then `d` ELSE 0 END) n_customer_jan,
SUM(CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202202' then `amount` ELSe 0 END) amount_sum_feb,
SUM(CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202202' then 1 ELSe 0 END) n_transaction_feb,
COUNT(DISTINCT CASE WHEN EXTRACT( YEAR_MONTH FROM `date` ) = '202202' then `d` ELSe 0 END) n_customer_feb
from tab1
GROUP BY `method`
http://www.sqlfiddle.com/#!9/31d8ef/10
much more interesting would be to make that dynamic

How to count number of nights booked per month with check-in and check-out dates having different months in SQL?

I have a dataset like the below dataset. I want to find the number of nights each id was occupied per month. For some rows, the check-in and checkout dates are in different months. I want to know how to write a query to have the occupancy per month. For example, for id=1, check-in: 2020-01-26 and checkout date: 2020-03-02. How can I have a table that shows January occupancy: 6, Feb occupancy: 29, and March occupancy: 1
id
check-in
checkout
1
2020-01-26
2020-03-02
2
2020-04-01
2020-04-20
3
2020-06-29
2020-07-03
The outcome should be like this:
id
Month
Occupancy
1
Jan
06
1
Feb
29
1
Mar
01
2
Apr
19
3
Jun
02
3
Jul
02
first, you need a numbers table or tally table , after you can easily to it using this query :
select c.id,
case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end as Checkin_date,
case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month))
end checout_date,
datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month)) end,
case when m.id <> 0
then last_day(adddate(checkin_date, interval m.id -1 month))
else adddate(checkin_date, interval -1 day) end
) daysdiff
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
order by c.id, checkin_date
this is works for any gap (for more than 1 year)
you can usedate_format to show month :
select
date_format(case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end, '%Y %M') as month_year
,sum(datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month)) end,
case when m.id <> 0
then last_day(adddate(checkin_date, interval m.id -1 month))
else adddate(checkin_date, interval -1 day) end
)) Occupancy
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
group by date_format(case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end, '%Y %M')
order by month_year
month_year | Occupancy
:------------ | --------:
2020 April | 20
2020 February | 29
2020 January | 6
2020 July | 3
2020 June | 2
2020 March | 2
db<>fiddle here
If I understand correctly, you want month-wise aggregated result of occupied inventory.
You can try below simple aggregate query as based on 'Group by' clause then add more criteria logic based on your need if required
select monthname(check_in) as 'Month', sum(dayofyear(check_out) - dayofyear(check_in)) as 'Occupied_days'
from inventory
where year(check_in)=year(check_out)
group by 1;
Note: Above query will work only for dataset where check_in & check_out happened within same year.
Check sample query output here in Fiddle

How to get the count of field of last 1 week ,last 1 month ,yesterday

I want to get count of customers city wise of today ,yesterday ,last week ,last month .
I want Result like
city today yesterday lastweek lastmnth
1 23 2 12 12
I have my table structure like the following
customers
c_id city_id c_name currentdate
1 1 Rama 2015-01-30 09:43:17
2 1 kavitha 2015-04-30 09:43:17
cities
city_id city_name
1 hyd
2 Wgl
I tried it with following .
select c.c_city, (select count(cr_id) as lastmonth from customer
where currentdate > DATE(NOW() - INTERVAL 30 DAY) )) from customers as c
left join cities as ci on c.city_id = ci.city_id group by c.city_id
Similarly to this:
SELECT city_id as city,
SUM(CASE WHEN LEFT(currentdate,10) = LEFT(NOW(),10) THEN 1 ELSE 0 END) as today,
SUM(CASE WHEN LEFT(currentdate,10) = LEFT(NOW()-INTERVAL 1 DAY,10) THEN 1 ELSE 0 END) as yesterday,
SUM(CASE WHEN currentdate > NOW()-INTERVAL 7 DAY THEN 1 ELSE 0 END) as lastweek,
SUM(CASE WHEN currentdate > NOW()-INTERVAL 30 DAY THEN 1 ELSE 0 END) as lastmnth
FROM customers GROUP BY city_id
For last week and last month, I'm assuming you mean 7 days back and 30 days back. If you however need data from previous week and from previous month (which doesn't make much sense to me in this context) you may need to rewrite the intervals.

MySQL results by date

Maybe there is a simple fix but I can't seam to figure it out. I'll try my best to explain my situation.
I'm working on a MySQL query that will return results within date range (in column A), and for date range - 1 year (in column B). I need to group results by month day and not by year. So I would like to have something like this:
2014 2013
----------------
01-01 6 8
01-03 7 0
01-04 4 1
01-08 0 13
01-21 11 7
In my current query (below) I get results like this (because of ELSE in CASE):
2014 2013
----------------
01-01 0 8
01-03 7 0
01-04 0 1
01-08 0 13
01-21 0 7
QUERY:
SELECT
DATE_FORMAT(table.date, '%e.%c.') AS date,
(CASE WHEN DATE(table.date) BETWEEN '2014-01-01' AND '2014-02-01' THEN ROUND(SUM(table.field), 2) ELSE 0 END) AS field_2014,
(CASE WHEN DATE(table.date) BETWEEN '2013-01-01' AND '2013-02-01' THEN ROUND(SUM(table.field), 2) ELSE 0 END) AS field_2013
FROM table
WHERE
(DATE(table.date) BETWEEN '2014-05-01' AND '2014-06-01' OR DATE(table.date) BETWEEN '2013-05-01' AND '2013-06-01')
GROUP BY
DATE_FORMAT(table.date, '%c.%e.')
What should I put in ELSE and how can I achieve this functionality?
Thank you for your time
You need aggregation functions. I would recommend:
SELECT DATE_FORMAT(t.date, '%e.%c.') AS date,
SUM(CASE WHEN year(t.date) = 2014 THEN ROUND(SUM(t.field), 2) ELSE 0 END) AS field_2014,
SUM(CASE WHEN year(t.date) = 2013 THEN ROUND(SUM(t.field), 2) ELSE 0 END) AS field_2013
FROM table t
WHERE year(t.date) in (2013, 2014) and month(t.date) = 5
GROUP BY DATE_FORMAT(t.date, '%c.%e.');
I would also recommend using the format '%m-%d'. Having the month then the year means that order by will work on the column. Having all the dates be the same width ("05/01" rather than "5/1") better corresponds to your desired output.

How do I count records based on time (month, year) ?

I have a table (myItems) with an item "id" and "date". Now i want to read out, how many items there are per month (i also want to distinguish between October 2013 and October 2014).
I started with:
SELECT Count(okt.id) AS Oktober, Count(nov.id) AS November
FROM `myItems` as okt,
`myItems` as nov
WHERE (okt.date between '2013-10-01' and '2013-10-31')
OR (nov.date between '2013-11-01' and '2013-11-30')
But it prints out a ridiculously large number. What am i doing wrong?
Try this. This will divide data into months and then do the COUNT :
SELECT SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
Demo: SQL Fiddle
With YEAR integrated:
SELECT 2013 as Year
, SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
WHERE YEAR(date) = 2013
UNION ALL
SELECT 2014 as Year
, SUM(CASE WHEN MONTH(date) = 10 THEN 1 ELSE 0 END) AS Oktober
, SUM(CASE WHEN MONTH(date) = 11 THEN 1 ELSE 0 END) AS November
FROM `myItems`
WHERE YEAR(date) = 2014;
;
Demo: Fiddle
With inspiration from #user77318
SELECT YEAR(date) as Year, month(date) as month, count(id) as count
FROM myItems
GROUP BY YEAR(date), MONTH(date);
I personally recommend this, more beautiful. Then you can do all the presentation stuffs on Application Layer.
Try this. Group the result by month:
SELECT month(date) as month, count(id) as count FROM myItems WHERE date between '2013-10-01' and '2013-11-30' GROUP BY MONTH(date);
Example of output result:
Month | Count
10 | 100
11 | 200
Probably you are not using join, you are just giving the conditions. First try to join these 2 tables with the primary keys or with some unique and common data column. Then try to execute above query. Somthiong like this:-
SELECT Count(okt.id) AS Oktober, Count(nov.id) AS November
FROM `myItems` as okt,
`myItems` as nov
WHERE okt.id = nov.id
AND (okt.date between '2013-10-01' and '2013-10-31')
OR (nov.date between '2013-11-01' and '2013-11-30');
May be this is helpful for you.