How to get Quarter from a date in Firebird SQL - date

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

Related

How to get value previous month & week?

Right now I'm getting an average for each month
SELECT EXTRACT(MONTH FROM date_time) AS month,
EXTRACT(YEAR FROM date_time) AS year,
avg("total")
FROM my_table
GROUP BY EXTRACT(MONTH FROM date_time), EXTRACT(YEAR FROM date_time)
But the SQL query needs to adjust so the total value current month - previous month
Is it possible?
For weekly
SELECT EXTRACT(WEEK FROM date_time) AS week,
EXTRACT(YEAR FROM date_time) AS year,
avg("total")
FROM my_table
GROUP BY EXTRACT(WEEK FROM date_time), EXTRACT(YEAR FROM date_time)
Yes, it's possible:
SELECT t1.month, t2.year, t1.tot - t2.tot FROM
(
SELECT EXTRACT(MONTH FROM date_time) AS month, EXTRACT(YEAR FROM date_time) AS year, avg("total") AS tot
FROM my_table GROUP BY EXTRACT(MONTH FROM date_time), EXTRACT(YEAR FROM date_time)
) t1
join (
SELECT EXTRACT(MONTH FROM date_time) AS month, EXTRACT(YEAR FROM date_time) AS year, avg("total") AS tot
FROM my_table GROUP BY EXTRACT(MONTH FROM date_time), EXTRACT(YEAR FROM date_time)
) t2
on ((t1.year = t2.year) and (t1.month = t2.month + 1)) or
((t1.year = t2.year + 1) and (t1.month = 1) and (t2.month = 12))
I have taken your select and converted it into two subselects, named them as t1 and t2 respectively and joined them by the criteria of left join.
Note that the very first month will not have a pair currently and if you need it nevertheless, then you can use left join and coalesce to make sure that even an unpaired item has a "pair" and a NULL for tot is defaulted to 0.
Note further that you can convert this subquery to a view for better readability.
If I get that correctly, you can first group avg(total) by yer and month, and the use LAG() window function to get previous month value, something like:
with my_table(date_time, total) as (
values
('2022-03-29', 10),
('2022-04-29', 12),
('2022-05-30', 20),
('2022-05-31', 30)
)
,grouped as (
SELECT EXTRACT('MONTH' FROM date_time::timestamp) AS month, EXTRACT('YEAR' FROM date_time::timestamp) AS year, avg("total") AS total
FROM my_table
GROUP BY EXTRACT('MONTH' FROM date_time::timestamp) , EXTRACT('YEAR' FROM date_time::timestamp)
)
SELECT *, LAG(total) OVER(ORDER BY year, month) as prev_month_total
FROM grouped

T-SQL Retrieve Last 6 Weeks Data to the Previous Saturday

SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= DATEADD(ww, -6, (Select MAX([TradingDate]) From FactSalesDetail))
ORDER BY TradingDate
Can anyone advise how I can convert the above WHERE Clause from retrieving the last 6 weeks data from Max Date in my Fact Table to the last 6 weeks to the Previous Saturday?
So as of Today that would Saturday 1st Jan and then back 6 weeks from that?
Using the current weekday can get you last Saturday.
And if you bring ##DATEFIRST into the equation then it won't depend on the DATEFIRST setting.
SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())))
AND TradingDate <= CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))
ORDER BY TradingDate
Test snippet for date range
SET DATEFIRST 7;
SELECT
datename(weekday, date_now) AS weekday_now, date_now
, datename(weekday, date1) AS wd1, date1
, datename(weekday, date2) AS wd2, date2
FROM
(
SELECT
CAST(GETDATE() AS DATE) AS date_now
, CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))) AS date1
, CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())) AS date2
) q
weekday_now
date_now
wd1
date1
wd2
date2
Tuesday
2022-01-04
Saturday
2021-11-20
Saturday
2022-01-01
db<>fiddle here

Build the calendar table for current year including weeknum divided to semester

for the below query i need divide the semesters starting from 1 to 26 .. first semester as 1 to 26 weeks and first semester should start from again 1 to 26
Any help is greating appreciated
DECLARE #StartDate DATETIME
DECLARE #CutoffDate DATETIME
SET #StartDate = Dateadd(yy, Datediff(yy, 0, Getdate()), 0)
SET #CutoffDate = Dateadd(yy, Datediff(yy, 0, Getdate()) + 1, -1)
SELECT day,
[week nu],
semester,
[semester week nu]
INTO #currentdates
FROM (SELECT Day = Dateadd(day, rn - 1, #StartDate),
Datepart(week, Dateadd(day, rn - 1, #StartDate)) [Week nu],
CASE
WHEN Month(Dateadd(day, rn - 1, #StartDate)) <= 6 THEN
'First Semester'
ELSE 'Second Semester'
END AS Semester,
Datepart(week, Dateadd(day, rn - 1, #StartDate)) AS
[Semester Week nu]
FROM (SELECT TOP (Datediff(day, #StartDate, #CutoffDate)) rn =
Row_number()
OVER (
ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;
I've got a couple of changes, first, you need to add 1 to your last datediff, your last date was December 30, not 31!
Second of all, I just get the date and week number in the first subselect, and then use these ine case statements for the select
The semester number is if week nu<=26,
The semester week nu is week nu if week nu<=26 else wwek nu -26
DECLARE #StartDate datetime DECLARE #CutoffDate datetime
SET #StartDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
SET #CutoffDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1)
SELECT DAY,
[Week nu],
case when [Week nu]<=26 then 'First Semester' Else 'Second Semester' end Semester,
case when [Week nu]<=26 then [Week nu] Else [Week nu]-26 end[Semester Week nu]
INTO #currentDates
FROM
(SELECT DAY = DATEADD(DAY, rn - 1, #StartDate),
DATEPART(WEEK,DATEADD(DAY, rn - 1, #StartDate)) [Week nu]
FROM
(SELECT TOP (DATEDIFF(DAY, #StartDate, #CutoffDate)+1) rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;

Last Working Day is showing null while on weekend

Here is my code but its showing null while today is friday. But I would like to get last working day.
-- Insert statements for procedure here
--Below is the param you would pass
DECLARE #dateToEvaluate date=GETDATE();
--Routine
DECLARE #startDate date=CAST('1/1/'+CAST(YEAR(#dateToEvaluate) AS char(4)) AS date); -- let's get the first of the year
WITH
tally(n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 FROM sys.all_columns),
dates AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS dt_id,
DATEADD(DAY,n,#startDate) AS dt,
DATENAME(WEEKDAY,DATEADD(DAY,n,#startdate)) AS dt_name
FROM tally
WHERE n<366 --arbitrary
AND DATEPART(WEEKDAY,DATEADD(DAY,n,#startDate)) NOT IN (6)
AND DATEADD(DAY,n,#startDate) NOT IN (SELECT CAST(HolidayDate AS date) FROM Holiday)),
curr_id(id) AS (SELECT dt_id FROM dates WHERE dt=#dateToEvaluate)
SELECT d.dt
FROM dates AS d
CROSS JOIN
curr_id c
WHERE d.dt_id+1=c.id
The code below will take any date and "walk backward" to find the previous week day (M-F) which is not in the #holidays table.
declare #currentdate datetime = '2015-03-22'
declare #holidays table (holiday datetime)
insert #holidays values ('2015-03-20')
;with cte as (
select
#currentdate k
union all
select
dateadd(day, -1, k)
from cte
where
k = #currentdate
or ((datepart(dw, k) + ##DATEFIRST - 1 - 1) % 7) + 1 > 5 --determine day of week independent of culture
or k in (select holiday from #holidays)
)
select min(k) from cte
The dates table doesn't have any FRIDAY dates in it. Change the NOT IN (6) to NOT IN (1, 7). This will remove Saturday and Sundays from the dates table.

Getting the start date and end date of all weeks by giving the year

I have a query which displays a set of 52 numbers along with the respective dates of that week
SELECT kkk, TO_CHAR (start_date, 'DD-MON-YYYY'),
TO_CHAR (start_date + 6, 'DD-MON-YYYY') AS end_day
FROM (SELECT TRUNC (TRUNC (TO_DATE ('2014', 'YYYY'), 'YYYY') + 1 * 7,
'IW'
)
- 1 start_date,
ROWNUM AS kkk
FROM DUAL
CONNECT BY ROWNUM <= 52);
but the problem with this query is that I am only getting the first week dates but not for the next consecutive weeks.Please help
Try like this,
SELECT kkk,
TO_CHAR(start_date, 'DD-MON-YYYY') start_date,
TO_CHAR(start_date + 6, 'DD-MON-YYYY') end_day
FROM(
SELECT TRUNC(Trunc(to_date('2014', 'YYYY'),'YYYY')+ LEVEL * 7,'IW')-1 start_date ,
ROWNUM kkk
FROM duaL
CONNECT BY LEVEL <= 52
);
Instead of ROWNUM you can also use LEVEL, Like,
SELECT TRUNC(Trunc(to_date('2014', 'YYYY'),'YYYY')+ LEVEL * 7,'IW')-1 start_date ,
level kkk
FROM duaL
CONNECT BY LEVEL <= 52