I want to display year and month names as column names between two dates inside my procedure as below
year jan Feb ......Dec
---- ----- ----- -----
2016 val1 val2 val3
2017 val4 val5 val6
some one help me to do this
You could do something like this if i understand you question correctly to generate the desired resultset.
TIMESTAMPDIFF(DAY.... + INTERVAL 1 MONTH) makes it possible to calculate the days within a month.
Please note that months have to be right in every TIMESTAMPDIFF(DAY, '2016-01-01', '2016-01-01' + INTERVAL 1 MONTH) AS 'Jan' line and it should work.
Query
SELECT
'2016' AS YEAR
, TIMESTAMPDIFF(DAY, '2016-01-01', '2016-01-01' + INTERVAL 1 MONTH) AS 'Jan'
, TIMESTAMPDIFF(DAY, '2016-02-01', '2016-02-01' + INTERVAL 1 MONTH) AS 'Feb'
...
, TIMESTAMPDIFF(DAY, '2016-12-01', '2016-12-01' + INTERVAL 1 MONTH) AS 'Dec'
UNION ALL
SELECT
'2017' AS YEAR
, TIMESTAMPDIFF(DAY, '2017-01-01', '2017-01-01' + INTERVAL 1 MONTH) AS 'Jan'
, TIMESTAMPDIFF(DAY, '2017-02-01', '2017-02-01' + INTERVAL 1 MONTH) AS 'Feb'
...
, TIMESTAMPDIFF(DAY, '2017-12-01', '2017-12-01' + INTERVAL 1 MONTH) AS 'Dec'
Result
year Jan Feb Dec
------ ------ ------ --------
2016 31 29 31
2017 31 28 31
Or this query makes it eazier to add a new year and less code duplication.
Query
SELECT
years.year
, TIMESTAMPDIFF(DAY, CONCAT(years.year, '-01-01'), CONCAT(years.year, '-01-01') + INTERVAL 1 MONTH) AS 'Jan'
, TIMESTAMPDIFF(DAY, CONCAT(years.year, '-02-01'), CONCAT(years.year, '-02-01') + INTERVAL 1 MONTH) AS 'Feb'
...
, TIMESTAMPDIFF(DAY, CONCAT(years.year, '-12-01'), CONCAT(years.year, '-12-01') + INTERVAL 1 MONTH) AS 'Dec'
FROM (
SELECT
'2016' AS YEAR
UNION
ALL
SELECT
'2017' AS YEAR
)
AS years
Result
year Jan Feb Dec
------ ------ ------ --------
2016 31 29 31
2017 31 28 31
Related
I am trying to write a query to get the last 4 weeks (Mon-Sun) of data. I want every week of data to be stored with an individual and shared table.
every week data store based on name if same name repeated on single week amt should sum and if multiple name it should be show data individual, To see an example of what I am looking for, I have included the desired input and output below.
this is my table
date
amt
name
2022-04-29
5
a
2022-04-28
10
b
2022-04-25
11
a
2022-04-23
15
b
2022-04-21
20
b
2022-04-16
20
a
2022-04-11
10
a
2022-04-10
5
b
2022-04-05
5
b
i want output like this
date
sum(amt)
name
2022-04-25 to 2020-04-29
16
a
2022-04-25 to 2020-04-29
10
b
2022-04-18 to 2022-04-24
35
b
2022-04-11 to 2022-04-17
30
a
2022-04-04 to 2022-04-10
10
b
I would appreciate any pointers or 'best-practises' which I should employ to achieve this task.
You can try to use DATE_ADD with WEEKDAY get week first day and end day.
SELECT
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END 'date',
SUM(amt)
FROM T
GROUP BY
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END
sqlfiddle
EDIT
I saw you edit your question, you can just add name in group by
SELECT
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')) 'date',
SUM(amt),
name
FROM T
GROUP BY
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')),
name
ORDER BY 1 desc
sqlfiddle
This is in SQL Server, and just a mess about. Hopefully it can be of some help.
with cteWeekStarts
as
(
select
n,dateadd(week,-n,DATEADD(week, DATEDIFF(week, -1, getdate()), -1)) as START_DATE
from
(values (1),(2),(3),(4)) as t(n)
), cteStartDatesAndEndDates
as
(
select *,dateadd(day,-1,lead(c.start_date) over (order by c.n desc)) as END_DATE
from cteWeekStarts as c
)
,cteSalesSumByDate
as
(
select s.SalesDate,sum(s.salesvalue) as sum_amt from
tblSales as s
group by s.SalesDate
)
select c3.n as WeekNum,c3.START_DATE,isnull(c3.END_DATE,
dateadd(day,6,c3.start_date)) as END_DATE,
(select sum(c2.sum_amt) from cteSalesSumByDate as c2 where c2.SalesDate
between c3.START_DATE and c3.END_DATE) as AMT
from cteStartDatesAndEndDates as c3
order by c3.n desc
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
I want to query row to view registered record based on previous quarterly month, for example:
current month / year: Jan 2018
the query should show all records by registered month which is: Oct 2017, Jul 2017, Apr 2017 and so on.
I use below query but only can select rows for last 3 month.
SELECT name, date, amount, agreement, bank
FROM `account`
WHERE (YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 3 MONTH) AND MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 3 MONTH))
You can do arithmetic like this:
select a.*
from account a
where mod(month(date), 3) = mod(month(current_date), 3);
You seem to understand how to handle the year component, but something like:
and date >= curdate() - interval 1 year
Try This One, Manually
select *
from account
Where current_date >= dateadd(year, -1, Getdate())
And Month(current_date) In (
Month(Getdate()),
(Case When Month(Getdate())+3 > 12 Then Month(Getdate())+3-12 Else Month(Getdate())+3 End),
(Case When Month(Getdate())+6 > 12 Then Month(Getdate())+6-12 Else Month(Getdate())+6 End),
(Case When Month(Getdate())+9 > 12 Then Month(Getdate())+9-12 Else Month(Getdate())+9 End)
)
I've been using MONTH() function to get the months and grouping by month, like this example query.
SELECT
t1.ano,
t1.mes,
tempo_extra,
tempo_ativo,
tempo_extra / tempo_ativo AS volume_extra
FROM
(SELECT
YEAR(`data`) AS ano,
MONTH(`data`) AS mes,
SUM(tempo) AS tempo_extra
FROM
rh.aprovacoes
WHERE
(tipo = 'BH' OR tipo = 'HE')
AND estado = 1
AND YEAR(aprovacoes.`data`) = 2016
GROUP BY MONTH(`data`)) AS t1
LEFT JOIN
(SELECT
MONTH(`data`) AS mes, SUM(ativo) AS tempo_ativo
FROM
rh.processamento
GROUP BY MONTH(`data`)) AS t2 ON t1.mes = t2.mes
ORDER BY mes DESC;
How can i make months start on 23rd of the last month and end on 22nd of the current month.
For example, April starting on March 23rd and end on April 22nd.
Simply subtract 22 days from your date and add a month:
(`data` - interval 22 day) + interval 1 month
March 22 => February 28 or 29 => March 28 or 29
March 23 => March 1 => April 1
April 22 => March 31 => April 30
April 23 => April 1 => May 1
SQL fiddle: http://sqlfiddle.com/#!9/9eecb7d/54883
Your query joins records regardless of the year by the way. I don't think this is desired, so in below query I've corrected this.
SELECT t1.ano, t1.mes, tempo_extra, tempo_ativo, tempo_extra/tempo_ativo AS volume_extra
FROM
(
SELECT
YEAR(data - interval 22 day + interval 1 month) AS ano,
MONTH(data - interval 22 day + interval 1 month) AS mes,
SUM(tempo) AS tempo_extra
FROM rh.aprovacoes
WHERE (tipo = 'BH' OR tipo = 'HE')
AND estado = 1
AND YEAR(aprovacoes.data - interval 22 day + interval 1 month) = 2016
GROUP BY
YEAR(data - interval 22 day + interval 1 month),
MONTH(data - interval 22 day + interval 1 month)
) AS t1
LEFT JOIN
(
SELECT
YEAR(data - interval 22 day + interval 1 month) AS ano,
MONTH(data - interval 22 day + interval 1 month) AS mes,
SUM(ativo) AS tempo_ativo
FROM rh.processamento
GROUP BY
YEAR(data - interval 22 day + interval 1 month),
MONTH(data - interval 22 day + interval 1 month)
) AS t2 ON t1.ano = t2.ano AND t1.mes = t2.mes
ORDER BY t1.ano DESC, t1.mes DESC;
I have the following data structure in my table:
id member_from member_till
1 2014/03/01 2014/05/18
2 2014/01/09 2014/08/13
...
How can i get a count of active members for the last 12 month, grouped by month?
Ex:
...
2014/12/01,5
2015/01/01,12
As a future development is it possible to make the count the average of the first and last day of each month?
First of all you need the last twelve months. Then outer-join the members and count those where the month is in the membership range.
select
date_format(all_months.someday, '%Y %m') as mymonth,
count(membership.member_from) as members
from
(
select current_date as someday
union all
select date_add(current_date, interval -1 month)
union all
select date_add(current_date, interval -2 month)
union all
select date_add(current_date, interval -3 month)
union all
select date_add(current_date, interval -4 month)
union all
select date_add(current_date, interval -5 month)
union all
select date_add(current_date, interval -6 month)
union all
select date_add(current_date, interval -7 month)
union all
select date_add(current_date, interval -8 month)
union all
select date_add(current_date, interval -9 month)
union all
select date_add(current_date, interval -10 month)
union all
select date_add(current_date, interval -11 month)
) all_months
left join membership
on date_format(all_months.someday, '%Y %m')
between
date_format(membership.member_from, '%Y %m')
and
date_format(membership.member_till, '%Y %m')
group by date_format(all_months.someday, '%Y %m');
SQL fiddle: http://www.sqlfiddle.com/#!2/6dc5a/10.
As to your future requirement: You can join the membership table twice, once for the members on the first of a month, once for the last of the month (loosing those who participated only some days in the middle of a month). Then add both counts and divide by two.
You can try with SQL Query:
SELECT `member_from`, count(id) FROM tbl_test WHERE `member_from` BETWEEN <From date> AND <To date> GROUP BY `member_from`;
Complete with future requirement:
SELECT
d.ymonth,
COUNT(m.member_from) total,
COALESCE(SUM(d.fday BETWEEN m.member_from AND m.member_till), 0) total_fom,
COALESCE(SUM(d.lday BETWEEN m.member_from AND m.member_till), 0) total_lom
FROM
(
SELECT
CAST(#first_day := #first_day + INTERVAL 1 MONTH AS DATE) fday,
LAST_DAY(#first_day) lday,
DATE_FORMAT(#first_day, '%Y-%m') ymonth
FROM
information_schema.collations
CROSS JOIN
(SELECT #first_day := LAST_DAY(CURRENT_DATE) - INTERVAL 13 MONTH + INTERVAL 1 DAY) x
LIMIT 12
) d
LEFT JOIN
membership m
ON d.lday >= m.member_from
AND d.fday <= m.member_till
GROUP BY d.ymonth
The subquery generates a virtual lookup table with 3 columns:
+ ---------- + ---------- + ------- +
| fday | lday | ymonth |
+ ---------- + ---------- + ------- +
| 2014-02-01 | 2014-02-28 | 2014-02 |
| \/ | \/ | \/ |
| 2015-01-01 | 2015-01-31 | 2015-01 |
+ ---------- + ---------- + ------- +
Then the membership table can be joined on the overlaps member_from-member_till and the beginning and ending of each month.