After certain week of 2022 and continue with this new year - sql

I would like to request some advice about how to set a Where Condition, but after a certain week
What I mean is:
I have dirty data before a specific week of 2022, so I made this:
DATEPART(WK, SA.FECHAE) >= 44
AND
YEAR(SA.FECHAE) >= 2022
But, We're on 2023, so, I need to add the new information of this new year year too into the query.
The query result shows me until 12-31-2022 and need it until today after the week 44 of 2022

...
WHERE (
DATEPART(WEEK, SA.FECHAE) >= 44
AND YEAR(SA.FECHAE) = 2022
)
OR (
YEAR(SA.FECHAE) >= 2023
)
In the OPs question they ask how to add an additional date range to their WHERE clause. The addition of this OR allows a second date range (in this case anything where the year is greater than or equal to 2023) to match the predicate and be returned, without impacting the original.
Plain English definition of the amended where clause:
Week 44 of 2022, or any week of any year from 2023 forward.

Related

Custom month numbers that take last 30 days instead of Number of month (SQL Server)

I am trying to create a lag function to return current month and last month streams for an artist.
Instead of returning streams for Feb vs Jan, I wan the function to use the last 30 days as a period for current month, and the previous 30 days as the previous month.
The query that I am currently using is this:
SELECT
DATEPART(month, date) AS month,
artist,
SUM([Streams]) AS streams,
LAG(SUM([Streams])) OVER (PARTITION BY artist ORDER BY DATEPART(month, date)) AS previous_month_streams
FROM combined_artist
WHERE date > DATEADD(m, -2, DATEADD(DAY, 2 - DATEPART(WEEKDAY, GETDATE()-7), CAST(GETDATE()-7 AS DATE)))
GROUP BY DATEPART(month, date), artist;
While this works, it is not giving me the data I need. This is returning the sum of streams for February vs the Streams for the month of January. February seems very low because we only have one week worth of data in February.
My goal is to get the last 30 days from the max date in the table using a lag function. So if the max date is Feb. 7 2023, I want the current month to include data from Jan. 7 2023 - Feb. 7 2023, and the previous month to include data from Dec. 7 2022 - Jan. 7 2023. I am thinking to create a custom month date part that will start from the max date and give a month number to the last 30 days . (2 for Jan 7 - Feb 7, 1 for Dec 7 - Jan-7...) I am not sure how to go about this. This is in SQL Server and I am looking to use the lag function for performance reasons.
I think you could probably use something like datediff(d, date_you_care_about, max_date)/30 in your group by and partition by clauses.
The basic idea is that integer division rounds down, so if the difference between the dates is < 30, dividing it by 30 is 0. If the difference is >=30 but less than 60, dividing it by 30 is 1. And so forth.
You can see a proof of concept in this Fiddle.

Daily Partitioning and archiving

I'm trying to partition a table by month say Jan, Feb, Mar. The column through which I'll partition is a datetime type column with an ISO Format ('20190101', '20190201', etc).
For example, I have sales data for jan, feb, mar. I'd like the data to be partitioned by daily partitioned . ('20190101', '20190201','20190301' etc)
E.X:
Jan, Feb, Mar etc. Also I would like to keep the data less so I would like to delete daily day wise data keeping only 1 month data maximum, for example I will create jan 31 , feb 28 , mar 31, apr 30. How do I manage partition dynamically as some month is 31 days some are 28 days and 30 days. Also I need to retain only one month data for example if its, 1st of sep then I need to keep aug 31 days data, and can delete 31st jul day data now on 2nd sep I can delete 1st august data so I need to delete daily data and keep only 30 days data .
My question is: is it even possible? If it is, how an I automate the process using SSIS?
You may try this. As you want to remove previous 30 days data from current date or any specific date, so you can easily calculate the date range by subtracting 30 days from the current date.
For 30 days
--- Instead of getdate() you may use any of your date column for filter
delete from yourtable where yourdate < DATEADD( day, -30, getdate()) ---- here on place of 30 you may use any days you want to delete
For 1 month
--- Instead of getdate() you may use any of your date column for filter
delete from yourtable where yourdate < DATEADD( month, -1, getdate()) ---- here on place of 30 you may use any days you want to delete
Instead of having your partition boundaries be the end of the month, have them be the beginning. That is, do something like:
[2019-01-01, 2019-02-01),
[2019-02-01, 2019-03-01),
[2019-03-01, 2019-04-01),
[2019-04-01, 2019-05-01),
[2019-05-01, 2019-06-01),
etc
That is, the left-hand boundary is in the partition and the right-hand boundary isn't. If you're using actual Partitioning, you'd define your partition function as a "boundary left" function. See the documentation for more details.

SQL - check if an order date occurs after the second Saturday in July

I am querying against a table of 4 yrs of order transactions (pk = order number) and I'm looking to tag each record with particular date flags based on the order date - e.g., calendar year, calendar month, fiscal year, etc. There are date attributes that are specific to our business (e.g., not easily solved by a datepart function) that I'm having trouble with.
I was able to add "School Year" (for us that runs Aug 1 - July 31) using a case statement:
case
when datepart(month, oline.order_date_ready) between 8 and 12 then datepart(year, oline.order_date_ready)
else (datepart(year, oline.order_date_ready)-1)
end as school_yr
So for 1/19/2017, the above would return "2016", because to us the 2016 school year runs from Aug 1 2016 to July 31 2017.
But now I'm having trouble repeating the same kind of case statement for something called "Rollover Year". All of our order history tables are reset/"rolled over" on the 2nd Saturday in July every calendar year, so for example the most recent rollover date was Saturday July 9th 2016. Click to view - rollover year date ranges
My above case statement doesn't apply anymore because I can't just add "datepart(month, oline.order_date_ready) = 7" - I don't need the whole month of July, I just need all the orders occurring after the 2nd Saturday in that July. So in this example, I need everything occurring from Sat July 9 2016 to today to be flagged as rollover_date = 2016.
Is there a flexible way to do this without hard coding previous/future rollover dates into another table? That's the only way I can think to solve it currently, but I'm sure there must be a better way.
Thanks!
If you ask for the day-of-the-week of July 1st, then from there it's simple arithmetic, right? This query gives results matching your image:
SELECT y,
CONCAT(y, '-07-01')::timestamp +
CONCAT(6 - EXTRACT(DOW FROM CONCAT(y, '-07-01')::timestamp) + 7, ' days')::interval
FROM generate_series(2013, 2020) s(y)
ORDER BY y DESC
;
So given any date d from year y, if it comes before the 2nd Saturday of July, give it fiscal year y - 1. Otherwise give it fiscal year (school year?) y.

Get month name with different month start and end dates

Getting the month for the current date is, obviously, straight forward, but I'm needing to get the month name with a different end date.
I need to get the month name with the start date of the month being the first Thursday after the first Wednesday of the month and the end date of the month being the first Wednesday of the following month. It's for an accounting thing, so I'm not going to argue with the spec!
e.g. for 2014, January would run from 9th Jan - 5th Feb, February would run from 6th February - 5th March, March would run from 6th March - 2nd April.
I would suggest that you create a table with your 'accounting months' in it, having a start date, end date and month name columns.
You could then query this to find the row where your date is between the start and end dates and return the month name. Putting this into a scalar function would then allow it to be reusable and relatively easily updated for next years months as well.
I think, as per Paddy's answer, a lookup table is the simplest thing to do. Here's one way to generate the rows for it:
; With Numbers(n) as (
select 4 union all select 5
), Months as (
select CONVERT(date,'20010104') as StartDt,CONVERT(date,'20010207') as EndDt,
DATENAME(month,'20010103') as Month
union all
select DATEADD(week,n1.n,StartDt),DATEADD(week,n2.n,EndDt),
DATENAME(month,DATEADD(week,n1.n,StartDt))
from Months,Numbers n1,Numbers n2 --Old-skool join, just for once
where DATEPART(day,DATEADD(week,n1.n,StartDt)) between 2 and 8 and
DATEPART(day,DATEADD(week,n2.n,EndDt)) between 1 and 7 and
StartDt < '21000101'
)
select * from Months option (maxrecursion 0)
(CW since this is effectively just an extension to Paddy's answer but I don't want to edit their answer, nor is it suitable for a comment

Convert date to first of current month if date is previous to current month

I have a query with an IIF() expression in one column that I am using to identify if a date is previous to the current month to then amend it if so. So if I run the query on 19th March 2014 and the EffFrom date is before 1st March 2014, I would want that column entry to now appear as 1st March 2014.
I am using the below expression which is pretty much doing what I want, however I know it is not considering the year -- i.e. it is changing an entry of 1st Jan 2015 to be 1st March 2014.
EffFrom:
IIf(Month([Table.Efffrom])"Less than symbol"Month(Date()),Date()-Day(Date())+1,[Table.Efffrom])
Can someone correct the expression for me?
I interpreted "if I run the query on 19th March 2014 and the efffrom date is before 1st March 2014 I would want that column entry to now appear as 1st March 2014" to mean you want something like this from a query run today (Mar 19th 2014):
id Efffrom adjusted_date
1 1/1/2014 3/1/2014
2 3/1/2014 3/1/2014
3 3/31/2014 3/31/2014
4 1/1/2015 1/1/2015
If that is correct, your IIf expression can use DateSerial to check whether Efffrom is before the first of this month, and transform the older dates.
SELECT
y.id,
y.Efffrom,
IIf
(
y.Efffrom < DateSerial(Year(Date()), Month(Date()), 1),
DateSerial(Year(Date()), Month(Date()), 1),
y.Efffrom
) AS adjusted_date
FROM YourTable AS y;
Here's what i do to get the first day of the next month
EffFrom: DateAdd("m",1,CDate(Format([Table.Efffrom],"m/\1/yy")))