In Cognos 10.2.1 - how can I use substring portions of an input parameter to create an expression to use for date comparison? - cognos-10

In Cognos 10.2.1 (FP7), I have a situation with two tables (see below), where a given transaction may be in the same "PERIOD", but what I want to do is to only give me results for transactions that have a date after the 15th of the month (i.e - the transaction may be in PERIOD 201510, and I only want transactons on/after 10/15/2015). The PERIOD is an input parameter that the user selects - I want to build the date from a portion of the PERIOD. (Before anyone complains about syntax, etc. - I've tried to simplify this as much as possible).
Given Table A:
ID varchar
PERIOD varchar
Given Table B:
ID varchar
TYPE varchar
TRANDATE timestamp2
Query1
[A.PERIOD]=?PARM1? <- this is the user selected input parameter
Query2
[B.TYPE] in ('A','B')
Then create a join from the results of Query1 and Query2 on the A.ID=B.ID to give Results1
I've tried the following (I'm keeping this as simple as I can - so I'm ONLY working with the YEAR portion of the period):
[Results1].[TRANDATE] >= concat(substring([Results1].[PERIOD],1,4),'-10-15T00:00:00.000000000')
[Results1].[TRANDATE] >= cast(concat(substring([Results1].[PERIOD],1,4),'-10-15T00:00:00.000000000'), timestamp2)
In both cases - Cognos won't validate the expression, or, if it does validate, I get a runtime error when running the report. In both cases, I get messages basically "literal does not match format string", even with the cast.
So - how can I get pieces/portions of the parameter, and slice/dice them to use as a date comparison as I mentioned above?

Given: Column [PERIOD] of type integer in the form YYYYMM, [TRANDATE] of type date/time
[TRANDATE] >= cast(cast(cast([PERIOD]/100,integer),varchar(4)) || '-' || cast(mod([PERIOD],100),varchar(2)) || '-15',date)
Given: Column [PERIOD] of type string in the form 'YYYYMM', [TRANDATE] of type date/time
[TRANDATE] >= cast(substring([PERIOD],1,4) || '-' || substring([PERIOD],5,2) || '-15',date)
The trick is that you don't have to build a full date/time string. You only have to build a string of format 'YYYY-MM-DD' in order to cast to a date type.

Related

insert statment make error

I am using oracle 12c with the username system. My problem is when I execute this insert statement that I took from oracle live sql site:
insert into emp
values(7788, 'SCOTT', 'ANALYST', 7566,to_date('13-JUL-87','dd-mm-rr') - 85,3000, null, 20);
it shows :
sql error ora-01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
incorrect. The input data did not contain a number where a number was
required by the format model.
*Action: Fix the input data or the date format model to make sure the
elements match in number and type. Then retry the operation.
what is this -85 after the to_date(..)
To handle dates, you would better use the ANSI format (date 'yyyy-mm-dd'):
insert into emp values(7788, 'SCOTT', 'ANALYST', 7566, date '1987-07-13'- 85,3000, null, 20);
If you need to use a to_date for some reason, you have to be sure that the format of your string exactly matches the format mask you use: if your month is written as 'JUL' you need 'MON' in the format mask and not 'mm'. 'mm' would match a month written as '07'.
Please notice that even with the right format mask, this way to write dates is dangerous, because it's based on the language of your DB.
The -85 means "subtract 85 days".

Sqlite date between

can you please help me why this code does not work?
I dont understand why the result include "2017".
SQLLITE
QUERY
SELECT issue_date as count FROM tablename where issue_date >= "08/08/2016" and issue_date < "09/01/2016"
Result
"08/08/2017"
"08/11/2017"
"08/18/2017"
"08/18/2017"
"08/22/2017"
"08/22/2017"
"08/28/2017"
"08/31/2017"
Create query
CREATE TABLE tablename (
issue_date datetime text not null
}
Insert query
INSERT INTO tablename (issue_date) values ("08/31/2017");
You are storing your dates in a non ANSI compliant format. As there is no formal date type in SQLite, and all dates are essentially stored as strings, your current date comparison will behave and sort as if you are comparing to text. It won't work, because you have the month first, followed by the day, followed by the year. To get text comparisons of dates to work correctly, use a format something like this:
yyyy-mm-dd
You should change the format you use to store dates, but one workaround would be to build the issue date in the correct format and then do the comparison, also against a date string in the same correct format:
SELECT
issue_date AS count
FROM tablename
WHERE
SUBSTR(issue_date, 7, 4) || '-' ||
SUBSTR(issue_date, 1, 2) || '-' ||
SUBSTR(issue_date, 4, 2) BETWEEN '2016-08-08' AND '2016-09-01'
SQLite's data types does not have a real DATETIME type. It only has NULL, INTEGER, REAL, TEXT and BLOB. Any other type is converted to these, so what it is doing in your case is storing those values as strings, and this comparing as strings.
I personally prefer to store the dates as UNIX timestamps (hence integers) to avoid complicating the SQL queries and simplify the whole thing (although the values in database will become less human-readable).
Because you specified the query with AND. So it matches your query. Use BETWEEN expression.
expression BETWEEN value1 AND value2;

In Teradata, trying to convert Timestamp(6) to timestamp(0)

A is in the format of timestamp(6). I need it in timestamp(0). The code I am using is the following:
cast(cast(A AS date) as timestamp(0))
FROM 'table'
where A >= '?StartDT'
After inputing the date I want for the parameter I get the 'Invalid timestamp' error.
If A is truly a Timestamp(6) then casting it first as a DATE will affectively trim off the time elements, so when you cast the result to a TIMESTAMP(0) you are going to end up with a time of 00:00:00.
You'll need to also cast the TIMESTAMP(6) field as a time and then add the results together like:
CAST(CAST(A AS DATE) AS TIMESTAMP(0)) + (CAST(A AS TIME(6)) - TIME '00:00:00' HOUR TO SECOND)
You can also use SUBSTRING() to snip off the last 6 characters of the TIMESTAMP(6) field and cast that resulting string to a TIMESTAMP(0):
CAST(SUBSTRING(CAST(A AS CHAR(26)) FROM 1 FOR 19) AS TIMESTAMP(0))
This doesn't address the INVALID TIMESTAMP error you are getting though. Are you certain that field A is a TIMESTAMP(6) and not a VARCHAR() that looks like a Timestamp? What happens when you remove the outer cast, are their any dates in the result that look like they wouldn't convert nicely to a timestamp? Something is not quite right here, and I suspect that it's in your data.

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

SQLite less than operator problem

I am using SQLite for a project and < symbol is not working in the query.
There is a table named Holidays which has a field of datatype datetime.
Suppose the table contains some dates of current year in the column HolidayDate.
SELECT HolidayDate
FROM Holidays
WHERE (HolidayDate >= '1/1/2011')
AND (HolidayDate <= '1/1/2012')
The < symbol in the above query is not working. > symbol in the above query is working well.
Please help me.
Try:
SELECT HolidayDate
FROM Holidays
WHERE HolidayDate >= date('2011-01-01')
AND HolidayDate <= date('2012-01-01')
(date format must be YYYY-MM-DD)
There is no datetime datatype in sqlite.
Sqlite only has 4 types:
integeral number
floating-point number
string (stored either as utf-8 or utf-16 and automatically converted)
blob
Moreover, sqlite is manifest-typed, which means any column can hold value of any type. The declared type is used for two things only:
inserted values are converted to the specified type if they seem to be convertible (and it does not seem to apply to values bound with sqlite_bind_* methods at all)
it hints the indexer or optimizer somehow (I just know it has trouble using indices when the column is not typed)
Even worse, sqlite will silently accept anything as type. It will interpret it as integeral type if it starts with "int", as string if it contains "char" or "text", as floating-point number if it is "real", "double" or "number" and as blob if it's "blob". In other cases the column is simply untyped, which poses no problem to sqlite given how little the typing means.
That means '1/1/2011' is simply a string and neither dates in format 'mm/dd/yyyy' nor dates in format 'dd/mm/yyyy' sort by date when sorted asciibetically (unicodebetically really).
If you stored the dates in ISO format ('yyyy-mm-dd'), the asciibetical sort would be compatible with date sort and you would have no problem.

Resources