I'm trying to create a table that looks like this (a table of the last 12 months)
month, year
10, 2016
9, 2016
8, 2016
7, 2016
6, 2016
5, 2016
4, 2016
3, 2016
2, 2016
1, 2016
12, 2015
11, 2015
The code I have looks something like this:
select date_part('month', current_date) as order_month,
select date_part('year', current_date) as order_year
union all
select date_part('month', current_date - interval '1 month') as order_month,
select date_part('year', current_date - interval '1 month') as order_year
union all
...
Is there a more concise way of writing this, rather than using 11 unions?
generate_series(start, stop, step) will be useful such that
SELECT
EXTRACT('month' FROM d) AS month,
EXTRACT('year' FROM d) AS year
FROM
GENERATE_SERIES(
now(),
now() - interval '12 months',
interval '-1 month'
) AS d
;
Related
I'm working on the Accrual Reversal query in PostgreSQL. The system running doesn't have the reversal flag. So I need to consider all the end of the day of previous month accrued invoices as the reversal amount. And need to union them all with the main query. I can do it for last month but invoice date are dynamic, user may give 2 years as invoice period. For those 2 years, all the previous month data should be considered as accrued reversal. Here is the query
select invoicename, * from accountpay where invoice_date between '2020-01-01' and '2021-12-31'
union all
select concat('Accured Reversal', invoicename) as reference, * from accountpay where accrual = true and invoice_date::date = (select concat(date_part('year',((('2021-12-30'::date) - interval '1 month'))), '-', date_part('month',((('2021-12-30'::date) - interval '1 month'))), '-01')::date + interval '1 month' - interval '1 day')
Please help me to do this.
Thanks in Advance
SELECT (
Date_trunc('MONTH',a) + interval '1 month -1 day ')
as last_day_of_month
FROM generate_series(
'2020-01-01 00:00'::timestamp
- interval '12 months',
'2022-01-01 00:00',
'1 month') as dt(a);
get last_day_of_month from '2020-01-01 00:00' till '2022-01-01 00:00'
Then your sql would be
invoice_date in
(SELECT (Date_trunc('MONTH',a) + interval '1 month -1 day ')
as last_day_of_month
FROM generate_series(
'2020-01-01 00:00'::timestamp
- interval '12 months',
'2021-01-01 00:00',
'1 month') as dt(a))
This will get the last day of last 12 months so the number of months will be place holder (dynamic) and all the last day of the months will be in IN clause.
SQL re-written:
WITH date_cte AS
(
SELECT Date_trunc('MONTH',dt)+ interval '1 month -1 day ' last_day_of_month
FROM generate_series('2021-11-30 00:00:00'::timestamp - interval '12 months','2021-11-30 00:00:00','1 month') t(dt))
select invoicename, * from accountpay where invoice_date between '2020-01-01' and '2021-12-31'
union all
select concat('Accured Reversal', invoicename) as reference, * from accountpay where accrual = true and invoice_date::date in (select * from date_cte);
Basically , the last dates are generated this way for 12 months:
WITH date_cte AS
(
SELECT Date_trunc('MONTH',dt)+ interval '1 month -1 day ' last_day_of_month
FROM generate_series('2021-11-30 00:00:00'::timestamp - interval '12 months','2021-11-30 00:00:00','1 month') t(dt))
SELECT *
FROM date_cte;
last_day_of_month
---------------------
2020-11-30 00:00:00
2020-12-31 00:00:00
2021-01-31 00:00:00
2021-02-28 00:00:00
2021-03-31 00:00:00
2021-04-30 00:00:00
2021-05-31 00:00:00
2021-06-30 00:00:00
2021-07-31 00:00:00
2021-08-31 00:00:00
2021-09-30 00:00:00
2021-10-31 00:00:00
2021-11-30 00:00:00
You can replace 12 months by any number of months or you can make it year too like:
...generate_series('2021-11-30 00:00:00'::timestamp - interval '1 year','2021-11-30 00:00:00','1 month')
SELECT to_char(date_trunc('day', (current_date - days)), 'YYYY-MM-DD')
AS date
FROM generate_series(0, 365, 1)
AS days
result
2021-11-12
2021-11-11
2021-11-10
2021-11-09
2021-11-08
2021-11-07 .....
2020-11-16
2020-11-15
2020-11-14
2020-11-13
2020-11-12 ..... end
How do I exclude weekend data from the year's worth of data?
SELECT to_char(running_day, 'YYYY-MM-DD') AS date
FROM (select current_date - generate_series(1, 365, 1)) AS t(running_day)
WHERE extract('isodow' from running_day) between 1 and 5
ORDER BY running_day;
Just add a WHERE clause:
SELECT to_char(day, 'YYYY-MM-DD') AS date
FROM generate_series(current_date - interval '1 year',
current_date,
interval '1 day') AS g(day)
where extract(isodow from g.day) not in (6,7)
I used the ISO definition of the day numbering with Monday = 1, Saturday = 6 and Sunday = 7.
You can use extract(dow ...) if you prefer Sunday = 0
I could not find a clear example of this online.
I want a moving average for the last 2 days based on this data:
create table expenses as (
select 'food' as expense, 5.0 as cost, current_date as date
union select 'food', 5.0, current_date - 1
union select 'food', 4.0, current_date - 2
union select 'food', 4.0, current_date - 3
union select 'food', 3.0, current_date - 4
union select 'food', 3.0, current_date - 5
union select 'entertainment', 9.0, current_date
union select 'entertainment', 9.0, current_date - 1
union select 'entertainment', 8.0, current_date - 2
union select 'entertainment', 8.0, current_date - 3
union select 'entertainment', 7.0, current_date - 4
union select 'entertainment', 7.0, current_date - 5
)
Here is the solution I put together
select
expense,
date,
cost,
avg(cost) over
(partition by expense order by date rows 2 preceding) as rolling_avg_cost
from expenses
which gives the result:
expense date cost rolling_avg_cost
entertainment Thursday, March 23, 2017 12:00 AM 7 7
entertainment Friday, March 24, 2017 12:00 AM 7 7
entertainment Saturday, March 25, 2017 12:00 AM 8 7.3
entertainment Sunday, March 26, 2017 12:00 AM 8 7.6
entertainment Monday, March 27, 2017 12:00 AM 9 8.3
entertainment Tuesday, March 28, 2017 12:00 AM 9 8.6
food Thursday, March 23, 2017 12:00 AM 3 3
food Friday, March 24, 2017 12:00 AM 3 3
food Saturday, March 25, 2017 12:00 AM 4 3.3
food Sunday, March 26, 2017 12:00 AM 4 3.6
food Monday, March 27, 2017 12:00 AM 5 4.3
food Tuesday, March 28, 2017 12:00 AM 5 4.6
As can be seen, the window for the rolling average is 3 days inclusive of the current row (i.e. the current row plus the previous two, all divided by 3).
can anyone tell me the logic of getting last year's last 2 months records from the next year Jan or feb ?. For eg: I want to compare the sales from Jan 2016 as current month and Dec 2015 as previous month and Nov 2015 as two months before. I tried like this, but not working if it is for Jan or feb
(case when extract(month from m.validfrom) = extract(month from current_date)-1 then 'Previous Month'
when extract(month from m.validfrom) = extract(month from current_date)-2 then 'Two Months Before'
when extract(month from m.validfrom) = extract(month from current_date) then 'Current Month' end ) as month,
date_trunc
case date_trunc('month', m.validfrom)
when date_trunc('month', current_date - interval '1 month') then 'Previous Month'
when date_trunc('month', current_date - interval '2 month') then 'Two Months Before'
when date_trunc('month', current_date) then 'Current Month'
end as month
I can easily get total sales in this month and previous month.
SELECT ‘This Mount’, SUM(Price) FROM Sales
WHERE EXTRACT(MONTH FROM OrderDate) = EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(YEAR FROM OrderDate) = EXTRACT(YEAR FROM CURRENT_DATE)
Union All
SELECT ‘Previous Month’, SUM(Price) FROM Sales
WHERE EXTRACT(MONTH FROM OrderDate) = EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(YEAR FROM OrderDate) = EXTRACT(YEAR FROM CURRENT_DATE)
I want to get the total sales in this quarter and previous quarter.
Getting quarter from a date is very easy with MS-SQL as follows:
SELECT DATEPART(QUARTER, #date)
How can I do this with Firebird?
Use DECODE function in conjunction with EXTRACT:
SELECT
DECODE(EXTRACT(MONTH FROM <date_field>),
1, 'I',
2, 'I',
3, 'I',
4, 'II',
5, 'II',
6, 'II',
7, 'III',
8, 'III',
9, 'III',
'IV')
FROM
<some_table>
Or just
SELECT
(EXTRACT(MONTH FROM <date_field>) - 1) / 3 + 1
FROM
<some_table>
SELECT dates,
EXTRACT(MONTH from dates) as SalesMonth,
floor(((EXTRACT(MONTH from dates)-1) / 3.0 + 1)) as QTR
from CustomerPO
where ((dates > '1/1/2016') and (dates < '12/31/2016'))
order by dates
Here, 'dates' is the field name of Order table 'CustomerPO'
SELECT dates,
EXTRACT(MONTH from dates) as SalesMonth,
ceil(EXTRACT(MONTH from dates) / 3) as QTR
from CustomerPO
where ((dates > '1/1/2016') and (dates < '12/31/2016'))
order by dates