How can I create a custom 'Week of Year' using a CASE Statement BETWEEN two dates over multiple weeks? - case

I'm currently trying to create a custom 'Week of Year' in Data Studio, starting on Saturday and ending on Friday. After many other attempts, I'm now trying to use a CASE statement.
The CASE statement is:
CASE
WHEN
date BETWEEN DATE(2022,07,30) AND DATE(2022,08,05)
THEN "WEEK 29"
DATE BETWEEN DATE(2022,08,06) AND DATE(2022,08,12)
THEN "WEEK 30"
DATE BETWEEN DATE(2022,08,13) AND DATE(2022,08,19)
THEN "WEEK 31"
ELSE NULL
END
This however, results in 'Syntax error: Expected "ELSE" or "END" but got "Date"'.
I guess this is a double question but does the above mean that I am unable to use the CASE statement more than once, e.g. can only apply it to Week 29 and not future weeks?
The second is, am I making this harder than it needs to be and there is an easier way to create a custom 'Week of Year' starting on Saturday and ending on Friday?
Any help is appreciated!

Every branch of a CASE expression in SQL needs to begin with either the WHEN or ELSE keywords (the latter can only occur at most once, at the end of the CASE expression). Try using this version:
CASE WHEN date BETWEEN DATE(2022,07,30) AND DATE(2022,08,05)
THEN 'WEEK 29'
WHEN DATE BETWEEN DATE(2022,08,06) AND DATE(2022,08,12)
THEN 'WEEK 30'
WHEN DATE BETWEEN DATE(2022,08,13) AND DATE(2022,08,19)
THEN 'WEEK 31'
ELSE NULL -- optional
END
Note that the ELSE branch in your CASE expression is optional here, since the default else value is NULL.

Related

TO_DATE yy,yyyy gives me different results

If I run the below queries
select to_char( TO_DATE(SYSDATE-7,'DD/MM/YY') ,'year') from dual
The result is twenty seventeen
select to_char( TO_DATE(SYSDATE-7,'DD/MM/YYYY') ,'year') from dual
The result is seventeen
why don't I get twenty seventeen for the second query?
Because you are doing an unnecessary explicit conversion from string to date, which is doing an implicit conversion from date to string based on your NLS settings.
What you should be doing is just:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Because sysdate-7 is already a date, you should not be calling to_date() around that, with any format. As the to_date() function takes a string argument, your sysdate-7 expression has to be implicitly converted to a string first. So you are really doing:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
which is using your NLS_DATE_FORMAT value for the implicit inner to_char() call, so if that is say 'DD-MON-RR' you're actually doing:
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
To see what's going on in there you need to see what the full generated date is, so for that I'm going to change the NLS_DATE_FORMAT for the session to show the full year:
alter session set nls_date_format = 'SYYYY-MM-DD';
select sysdate - 7 as raw_date,
to_char(sysdate - 7, 'DD-MON-RR') as implicit_string,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YY') as implcit_yy,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY') as implcit_yyyy
from dual;
RAW_DATE IMPLICIT_STRING IMPLCIT_YY IMPLCIT_YYY
----------- ------------------ ----------- -----------
2017-04-30 30-APR-17 2017-04-30 0017-04-30
Notice the different years in the last two values. The documentation has a section on format model matching. The string you are implicitly creating in the middle has a 2-digit year. When you convert the string '30-APR-17' back to a date using a YY model, it 'helpfully' assumes the current century, so the date ends up as 2017. But when you convert the same string using a YYYY model it thinks you really meant the value you passed in and so doesn't assume a century - and you passed it 17, so you end up with the year 17; that is, 0017 and not 2017. (You would also have got the answer you expected using RRRR, but it is much better to stick to YYYY and actually use 4-digit years everywhere - if you actually need to use a string at all.)
Essentially: don't rely on NLS settings or implicit conversions of dates to strings or vice versa.
In this case you don't need any conversions, so use the simpler statement at the top of this answer.
you should get 2017 for second query, not for the 1 query. Other possibility is NLS settings or session, software settings.
Apart from that you have to use 'YYYY' instead of 'YY' to get 2017

Converting a day and a year to a date in VBScript

I've seen a few similar questions/answers, but none of them answered my question/answered for VBS. I have a set of days that I would like to convert to dates for this year. However, when I try to convert them to dates, I get the wrong values because it uses the year 1900. Is there some way I can specify the year in the CDate function? I looked at the Calendar class, but that didn't apply because I'm using VBScript.
MsgBox(CDate(195))
MsgBox(CDate(196))
MsgBox(CDate(197))
MsgBox(CDate(198))
MsgBox(CDate(199))
These give me 7/13/1900, 7/14/1900, 7/15/1900, etc.
Use DateAdd to add a number of days to a start date obtained by DateSerial:
>> dt2014 = DateSerial(2014, 1, 1)
>> WScript.Echo dt2014
>>
01.01.2014
>> WScript.Echo DateAdd("d", 195, dt2014)
>>
15.07.2014
(German locale; lookout for a +-1 bias (adding to the first day of year))
Update wrt to #Bond's comment:
Even if you need to add many days to on start date (as I understood the task), using just DateSerial with many different day-parameters may well be more efficient.

convert to date and extract only the time

How could I get only time of a varchar2? I do:
select to_date(substr(fecha,10,16),'HH:MI:SS AM') from total;
But it gives me:
01/06/2014 5:50:01
01/06/2014 5:50:05
01/06/2014 5:50:05
01/06/2014 5:50:50
And I would like to have:
5:50:01
5:50:05
5:50:05
5:50:50
Any help? Please
Although it may not be what you expected, the code is working correctly. In Oracle, if you don't specify the day-month-year portion of a date it defaults to the first day of the current month. An Oracle DATE must always have a day/month/year - there's no way to have a time without a date in a DATE column or variable.
SQLFiddle here.
If you really want to have it display only the time portion of the date you'll just have to extract only the hours-minutes-seconds using TO_CHAR(date_value, 'HH24:MI:SS') and treat it as a character string.
Share and enjoy.
i think you should use both, to_char and to_date:
select to_char(to_date(fecha,'dd-mm-yyyy HH:MI:SS AM'),'HH:MI:SS AM')
time from total;

I need a sqlite equivalent of the folling msaccess query

Select distinct Format(DateAdd(""s""," & columnname & ",""1/1/1980 12:00:00 AM""), 'dd-MMM-yyyy') as A
I have assumed that the seconds to add and the original date are hard coded values below whilst awaiting clarifications requested in the comments.
To add a number of seconds to a date you can use:
select datetime('1980-01-01 00:00:00', "345000 seconds");
This gives the result: 1980-01-04 23:50:00
The example above is just under 4 days in seconds, if you want to truncate the result to just the date as implied by the query in your questions then you can wrap this inside a date function. However, this would give the result in the format "YYYY-MM-DD" rather than "DD-MMM-YYYY" as your access query does.
Unfortunately I cannot find any native SQLite function to convert a numeric month value to mmm format. You can do this manually with replace (similar to the answer to this question), but this is a bit messy.
If you are happy to live with the numeric months then you can simply use:
select strftime('%d-%m-%Y', '1980-01-01 00:00:00', "345000 seconds");
This gives the result: 04-01-1980
More information on the SQLite date / time functions can be found here.

Doing datetime math in a function call in an Oracle query

Ok, I got the first part of my question answered, so here's the second part. :-) In a PLSQL query, I have criteria that looks like this:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(:DateEnd)
Now, I don't want to use :DateEnd itself -- I want to add 1 day so that when it compares the datetime to midnight, I get midnight of the next day. Unfortunately, when I do
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(:DateEnd + 1)
I get "ORA-06553: PLS-306: wrong number or types of arguments in call to 'CONVERT_DATE_TO_ID'". ":DateEnd + interval '1' day" gives me "ORA-30081: invalid data type for datetime/interval arithmetic" (where :DateEnd is bound to 31-MAY-2012). If I do "convert_date_to_id(add_months(:DateEnd, 1))", it works fine. Any thoughts? Thanks.
ETA: I should clarify that this is an SSRS 2008 R2 project, and DateBegin and DateEnd are defined in the report parameters as DateTime parameters. My current workaround involves setting the :DateEnd query parameter equal to the #DateEnd report parameter + 1, but I'm worried that someday I'll forget to document this properly and confuse the heck out of whomever's trying to maintain the report (and it might be me). I don't want to pass string parameters, as suggested before.
I'm thinking that the parameters being DateTime is root of the problem. Microsoft DateTime datatypes are way more granular than Oracle's in that it supports fractional seconds and Oracle DATE format does not (Oracle TIMESTAMP does however).
Since ADD_MONTHS just spits back whatever it's passed in DATE datatype (i.e. passed TIMESTAMP becomes DATE). So maybe you can convert the parameter and add the day that way:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(CAST(:DateEnd as DATE)+1)
Alternatively, forget about conversions and date arithmetic on the parameters and subtract a day from the second clinicalDate:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate - 1 < ml.convert_date_to_id(:DateEnd)
Assuming that ml.convert_date_to_id takes a DATE as an input parameter rather than a VARCHAR2 that represents a date, and assuming that the :DateEnd bind variable is a VARCHAR2, you would need something like
ml.convert_date_to_id( to_date( :DateEnd, 'DD-MON-YYYY' ) + 1 )
or
ml.convert_date_to_id( to_date( :DateEnd, 'DD-MON-YYYY' ) + interval '1' day )
Use to_date to convert the value. For example:
select &date + 1 from dual
Informing to_date('29052012','ddmmyyyy') works fine
Informing '29-may-2012' gives ORA-01722: invalid number

Resources