negative/minus operator in case statement - postgresql

I'm currently trying to understand some code and for the life of me I can't figure out what the negative/minus operator is doing inside of the CASE statement. When I try removing it, it breaks the visualization.
This is part of a bigger puzzle of figuring out exactly what this portion of the query does. I know it's a counter of some sort that checks the year, and if the year is 2017, then extracts the month. If it isn't 2017, then it extracts the month 12 months from now, but I'm not sure how it works beyond that. Any insight into the negative/minus operators in this CASE statement or this function in general would be appreciated.
MAX(
CASE WHEN (- CASE WHEN EXTRACT(year FROM premium_creation_date) = 2017 --?? some sort of counter
THEN EXTRACT(month FROM premium_creation_date)
ELSE
EXTRACT(month FROM premium_creation_date) + 12
END
+ CASE WHEN EXTRACT(year FROM user_creation_date) = 2017
THEN EXTRACT(month FROM user_creation_date)
ELSE
EXTRACT(month FROM user_creation_date) + 12
END
) = 1
THEN unique_user_count
ELSE
NULL
END
) AS restriction

The - changes the sign of the result of the CASE.
The CASE gives the month of the premium_creation_date when the year of that date is 2017. Otherwise it's the month plus 12.
So e.g. 2017-05-04 yields 5 in the CASE, which makes -5 after the - took effect. For 2018-07-06 that would be 7 + 12 = 19 and therefore -19.
Actually you could turn this whole thing around and subtract the first CASE from the second. That may look clearer.

Related

Date listing at postgresql

and date(p.date_of_sale) <= current_date
I try this code and I got an answer like that.
.
But an error is shown like that.
.
Please watch 2 screenshots because I am not fluent in English and I don't know how to explain with text. That's why I add 2 screenshots.
Your problem comes from to_char(p.date_of_sale, 'yyyy "-week" iw') where
iw = week number of ISO 8601 week-numbering year (01–53; the first Thursday of the year is in week 1)
whereas yyyy = the year on 4 digits (not the ISO8601 year)
These two parameters are sometimes not consistent for instance for 2023 January the 1st :
SELECT to_char('20230101' :: date, 'yyyy') => 2023
SELECT to_char('20230101' :: date, 'iw') => 52
If you want to be consistent, you can either :
select to_char('20230101' :: date, 'YYYY"-week" w') => 2023-week 1
or
select to_char('20230101' :: date, 'IYYY"-week" iw') => 2022-week 52 (ISO8601 year and week)
see dbfiddle

Working with Year , week and Leap year in SQL Server

I'm trying to work with Year and Week in combination and would like to include leap years when they occur.
In my code I'm only adding year + week and I'm not getting what I desire. I would like to have '202101' if I change my code to '+3' because this year there are 53 weeks and the 54 week should 01.
(SELECT
LEFT(CONVERT(VARCHAR(10), GETDATE(), 120), 4) +
CAST((DATEPART(ISOWK, GETDATE()) + 3) AS NVARCHAR(2)))
I would like to be able to change my code like this
...GETDATE()) + 2) in my code should return 202053
...GETDATE()) + 3) in my code should return 202001
...GETDATE()) + 4) in my code should return 202002
etc...
Might it be that i should change my code and not have it as a 2 part YYYY and WW but rather combine it as a date? I would believe its a string now.

Combine, Group and Rename

Here is my current formula:
if left ({Command.NextDueDate},7) = "2016-01" then "January'16"
else if left ({Command.NextDueDate},7) = "2016-02" then "February'16"
...
else if left ({Command.NextDueDate},7) = "2017-01" then "January'17"
I take date Strings from my database formatted like 2016-01-05, 2016-01-06...2017-01-01. I use these as columns.
I want to look for the year (16), then month (01), then for next column look for year (16) again and month (2). Then I'd like to interpret the month as shortened month names, like Jan or Feb. Finally I'd want to join the data back together. So in the end it will work like this:
16 + 01 becomes Jan16
16 + 02 becomes Feb16
17 + 01 becomes Jan17
How can I do this without manually entering an if-else clause for each month of each year?
No need to hard code it - Use this formula to get the month and year:
MonthName(Month(CDateTime({Command.NextDueDate}))) +
Right(Left({Command.NextDueDate},4),2);
Don't use if/else statements when you can get the information through clever use of formulas. There are a few ways you can make Ankur's formula even better:
To get the short Month name, use: MonthName(Month(CDateTime({Command.NextDueDate})),True) The True at the end shortens the name to "Jan", "Feb", "Mar" and so on.
To get the Year, use Year(CDateTime({Command.NextDueDate}))
Combine the two formulas and it does all the work for you:
MonthName(Month(CDateTime({Command.NextDueDate})),True) +
Year(CDateTime({Command.NextDueDate}))

MS Access : Dealing with today's date in calculated field expression

Hi I am creating a table in MS Access to store the details of children in a school.
I have a field called YearGroup which needs to calculate the school year they are in based on their date of birth and whether they have been moved up or down a year.
I.e. if the expression deems they are six years old they should be placed in year 2. If they were moved down or up a year they should be in year 1 or 3 (this is based on another field in the table called YearModifier).
The code I have at the moment is this:
Year(Now()) - IIf(Month([DOB]) > 8, Year([DOB]) + 6 + [YearModifier], Year([DOB]) + 5 + [YearModifier])
My problem is that Year(Now()) is returning as invalid expression. Lots of websites have recognised using the Now() function and also I've tried Date() but nothing seems to be accepted by Access (The version is 2010).
What is going on? How can I get today's date in a calculated field expression?
Thanks
Try creating a query with all of the fields from your table, and then add an extra field YearGroup: Year(Now()) - IIf(Month([DOB]) > 8, Year([DOB]) + 6 + [YearModifier], Year([DOB]) + 5 + [YearModifier])
It appears that Date functions can't be used in calculated columns in tables.
You could use this to get the year, which might work in field expressions:
format(date(),"yyyy")
About your function (which I have re-written very slightly)
Year( Now() )
- Year([DOB])
- IIf( Month([DOB]) > 8
, 6
, 5 )
+ [YearModifier]
however!
I don't think you want to use now(). Which year they are in depend on their age at the 1st Sept at the start of the current academic year not now! Ok now will work until 31/dec/2015, so I must assume you will not be using the function after this date!
If you are you must use 2015 not Now().
Ok?
You can calculate the age of the children with a simple function:
Public Function AgeSimple( _
ByVal datDateOfBirth As Date) _
As Integer
' Returns the difference in full years from datDateOfBirth to current date.
'
' Calculates correctly for:
' leap years
' dates of 29. February
' date/time values with embedded time values
'
' DateAdd() is used for check for month end of February as it correctly
' returns Feb. 28. when adding a count of years to dates of Feb. 29.
' when the resulting year is a common year.
' After an idea of Markus G. Fischer.
'
' 2007-06-26. Cactus Data ApS, CPH.
Dim datToday As Date
Dim intAge As Integer
Dim intYears As Integer
datToday = Date
' Find difference in calendar years.
intYears = DateDiff("yyyy", datDateOfBirth, datToday)
If intYears > 0 Then
' Decrease by 1 if current date is earlier than birthday of current year
' using DateDiff to ignore a time portion of datDateOfBirth.
intAge = intYears - Abs(DateDiff("d", datToday, DateAdd("yyyy", intYears, datDateOfBirth)) > 0)
End If
AgeSimple = intAge
End Function
Then your expression would be something like this (ignoring the modifier):
ClassYear: IIf(AgeSimple([DOB]) > 6, 2, 1)

Count differnce of two Date's with Respect that every month has EXACT 30 days

I thought it was clear, but doesn't seem so.
This question is about T-SQL (since it's tagged with tsql :) )
So I couldn't find any out-of-the-box solution to calculate my problem.
Let's assume you have these two dateTimes:
DECLARE #start DATETIME = '2011-01-01',
#end DATETIME = '2011-04-15'
The difference of these two datetimes in Days should be quivalent to 105.
The calculation works as follows: For every full month add 30 days, for the rest add the days till the date is achieved.
I could program this, but it would be an enormous SQL-statement, which I find find kinda ugly.
Is there any simple solution for this, like a built-in function or something short?
Thanks in advance.
Does this do the trick?
;with dates as
(
SELECT
CAST ('2011-01-01' AS DATETIME) as start_date
,CAST('2011-04-15' AS DATETIME) as end_date
)
SELECT
start_date
,end_date
,CASE WHEN DATEDIFF(MM,start_date,end_date) = 0 THEN DAY(end_date) - DAY(start_date)
WHEN DAY(start_date) = 1 THEN (30 * (DATEDIFF(MM,start_date,end_date))) + DAY(end_date)
WHEN DAY(start_date) <> 1 THEN 30 * DATEDIFF(MM,start_date,end_date) + (DAY(end_date) - DAY(start_date))
END AS gap_in_days
FROM dates
Short Answer
There's no built in function, but you could pretty easily create your own to handle converting a datetime to an int. From there, the SQL you would have to write would be trivial.
Long Answer
There's no built in function that will do this, probably because every month doesn't have 30 days. :)
You can start with this:
DECLARE #start DATETIME = '2011-01-01',
#end DATETIME = '2011-04-15'
DECLARE #endConverted INT
SELECT #endConverted = DATEPART(month, #end) * 30
+ CASE
WHEN DATEPART(DAY, #end) <= 30
THEN datepart(DAY, #end)
ELSE 30
END
DECLARE #startConverted INT
SELECT #startConverted = DATEPART(MONTH, #start) * 30
+ CASE
WHEN DATEPART(DAY, #start) <= 30
THEN DATEPART(DAY, #start)
ELSE 30
END
SELECT #endConverted - #startConverted
This isn't beautiful SQL, but it works. Note that it returns 104 (because 15 days - 1 day = 14 days), but simple enough to tack on a + 1 to the end of the final select if you want to handle the boundry days differently.
Note that the math here could pretty easily be moved into a function, which would allow you to clean your SQL up. Let's assume you created a function called GetDateTimeAsInt which holds the math; your SQL could be as simple as
DECLARE #start INT = GetDateTimeAsInt('2011-01-01'),
#end INT = GetDateTimeAsInt('2011-04-15')
SELECT #end - #start -- may need to add 1 here
In my testing, this seems to work. It will return the same result as the DATEDIFF function for the date range you specify in your post, but this is because there are 2 days with 31 days and 1 day with 28, so effectively, Jan - April have 30 days each. If you use it with a wider date range, you'll begin to get different results with my code vs. the DATEDIFF function.
Hope this helps.
I use PERIODDIFF. To get the year and the month of the date, I use the function EXTRACT:
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
T-sql
SELECT DATEDIFF(dd, "2011-01-01","2011-04-15")