How do I make a working iif clause in MS Access - ms-access

So I just learned a Little Bit of SQL in Access in School and i got stuck. The task is to display classes and the date when they „started“ and when they will end. If one of those is empty I have to put the current year in. Here is what i got so far
Select
Klassen.K_Nr,
Klassen.K_Datumvon,
K_Datumbis
From
Klassen
Where
iif( (K_Datumvon Or K_Datumbis) Is Null, 2018)

The IIF function in JET Red SQL (as used by Microsoft Access) has this syntax:
https://support.office.com/en-us/article/iif-function-32436ecf-c629-48a3-9900-647539c764e3
IIf ( expr , truepart , falsepart )
In your query you'll want to use IIF in the SELECT part, not the WHERE part as it is not a predicate.
SELECT
K_Nr,
IIF( K_Datumvon IS NULL, DATE(), K_Datumvon ) AS K_Datumvon,
IIF( K_Datumbis IS NULL, DATE(), K_Datumbis ) AS K_Datumbis,
FROM
Klassen
Note this SQL uses DATE() to return the current date.

Related

MySQL Subquery Truncating Result with NULLIF

I have the following query:
SELECT
NULLIF(MAX(t.date),'2019-01-15') AS ended
FROM
totals t
This query correctly outputs a date:
> 2019-01-01
But if I reference this query inside of a subquery like so:
SELECT * FROM
(SELECT
NULLIF(MAX(t.date),'2019-01-15') AS ended
FROM
totals t) AS a
This version incorrectly produces a truncated result:
> 201
Can someone help me to understand this behavior and how best to work around it?
Additional Notes:
I am running MySQL version: "5.7.25 MySQL Community Server"
For anyone wanting to test this out, here is an example of a simple test table that is affected by this problem:
CREATE TABLE `totals` (
`date` date NOT NULL,
`value` decimal(10,0) DEFAULT NULL,
PRIMARY KEY (`date`)
);
INSERT INTO `totals` VALUES ('2018-01-01',2000000),('2019-01-01',3000000);
The issue here appears to be a subtle converting/casting issue happening within NULLIF. First, here is a version of your query which does in fact work as expected:
SELECT *
FROM
(
SELECT NULLIF(MAX(t.date), STR_TO_DATE('2019-01-15', '%Y-%m-%d') AS ended
FROM totals t
) AS a
What is happening with your current query is that MySQL is converting the call to MAX(t.date) to text, to match the text literal '2015-01-15'. By ensuring that both arguments to NULLIF are date type, you get the behavior you want.
As for why we are seeing 201 as the string result from the call to NULLIF, I don't have an explanation. But, I can cite the documentation for NULLIF here:
Returns NULL if expr1 = expr2 is true, otherwise returns expr1. This is the same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END.
It is a general rule in SQL that both the if and else branches of a CASE expression should always have the same type. Actually, if we violate this rule, in most databases the CASE expression won't even compile. Applying this to NULLIF means that we should always make sure that both arguments have the same type. Breaking from this rule might run on MySQL (similar to doing a non ANSI compliant GROUP BY with full mode turned off), but it is not something we should choose if we can avoid it.
My guess is that there's implicit datatype conversions happening.
As a workaround, I would take the return from the NULLIF function and convert/cast it back to DATE datatype. Simplest would be to wrap it in DATE() function.
SELECT
DATE( NULLIF(MAX(t.date),'2019-01-15') ) AS ended
^^^^^ ^
We could also try converting the string literal, convert that to a DATE, and see if that fixes the problem:
SELECT
NULLIF(MAX(t.date), DATE('2019-01-15') ) AS ended
^^^^^ ^
Or we can do both:
SELECT
DATE( NULLIF(MAX(t.date), DATE('2019-01-15') ) ) AS ended
^^^^^ ^
^^^^^ ^
There are other expressions we can use for the datatype conversion such as CAST(), CONVERT(), or STR_TO_DATE().
Or we could just use the simple + INTERVAL 0 DAY trick. e.g.
SELECT
NULLIF(MAX(t.date),'2019-01-15' + INTERVAL 0 DAY ) + INTERVAL 0 DAY AS ended
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^

SSIS Derived Column condition to replace null values based on a specific date

I am working on a SSIS Package that will populate a SharePoint 2013 list with data from other SP lists.
I have created a Derived Column in the package, which is intended to replace null based on dates that are greater than or equal to a specific date in the data list. However, I am having trouble with the expression. Below is a condition and expression example that I am have trouble with.
REPLACENULL(ColumnName,"mm/dd/yyyy" > = GETDATE())
Any assistance to point out what I am doing wrong is appreciated.
Use this expression:
((DT_DATE)"9-1-2016") >= (DT_DATE)ColumnName ? NULL((DT_WSTR, 50)) : ColumnName
Notice: REPLACENULL is not useful for you here. What REPLACENULL does is that it:
Returns the value of second expression parameter if the value of first expression parameter is NULL". (See here)
You don't want to replace NULL, you want NULL!
Syntax for REPLACENULL is REPLACENULL(expression 1,expression 2) where
expression 1 :
The result of this expression is checked against NULL.
expression 2 :
The result of this expression is returned if the first expression evaluates to NULL.
If you're trying to REPLACE NULL values of a column based on another column's datetime condition, try something like this :
[column_1] >= GETDATE() ? REPLACENULL([column_2],"desired value") : [column_2]

How to get String value from a boolean value using MySQL query in Jasper Studio

I have an SQL query to get results from my database table. When I run this query in Jasper Studio it should bring me following.
Nocte & Mane are boolean type colomns in the table. If the Nocte column is true then, it could show as a string ("Nocte") and this should same for the mane.
SQL Query
select * from medication where $X{IN,idmedication,list} order by `LastUpdated` desc
This is the query I am using in Jasper report and idmedication and list are parameters. LastUpdated is a timestamp. This list includes Integer values, which are the idMedications.
Have any ideas to do above task in Jasper Studio?
I can think of two approaches at the moment:
Use expressions when you design the report, it could be something like ($F{Nocte}?"Nocte":"something else")
Modify the query so that it returns varchar instead of boolean. For example:
select case when Nocte = 1 then "Nocte" else "something else" end Nocte
from your_table ...
the solution is something like bellow
(
${your_filed_name}==true?"Nocte"":"mane"
)
Hope this answer your question. And you can chain the condition or get into more complex expression.

UNIX_TIMESTAMP getting null

This is getting NULL, why?
select unix_timestamp(addtime(date(now()), time(from_unixtime(1426705199))))
For some reason, it is running correctly, however it only outputs NULL
I often find, when confronted with an error, that the manual can be a useful resource:
ADDTIME() adds expr2 to expr1 and returns the result. expr1 is a time or datetime expression, and expr2 is a time expression.
You are using a date value for expr1. Try casting it back to datetime expression:
select unix_timestamp(addtime(
timestamp(date(now()))
, time(from_unixtime(1426705199))))
This should work?
SELECT UNIX_TIMESTAMP(NOW())
If you want to get it from your own field then use this..
SELECT UNIX_TIMESTAMP(yourField);

Select 2 or more values in the IF statement

I want to implement following logic in my SQL query:
If some date is not set or it's year is 1970 then select real_date flag to null AND change date to current data, else - real_date is true and no need to change date.
real_date is not an actual field in the table but a flag I need to set up.
I can easily do this using 2 lines in my SELECT section:
, IF (actualDate is NULL OR YEAR(actualDate) = 1970, CURRENT_TIMESTAMP(), actualDate) as actual_date
, IF (actualDate is NULL OR YEAR(actualDate) = 1970, null, true) as real_date
And the question - is it the only way to do it? Don't really like the fact that I had to copy condition again. Can somehow the second select be moved to the first one?
Update: I need to select both actualDate (it will be either fixed to current time version or the actual stored value) and real_date (which will be true or false/null). Maybe I am missing something, but how could COALESCE function help here?
Update 2: Thanks again everyone. Learnt other ways to write it but all of them have check in 2 places. My idea was to have logical condition in only one place but doesn't seem to be possible.
Your variant is pretty and comfortable for supporting code in future, do not change anything.
You can use the COALESCE function.
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
You can also use CASE WHEN ... THEN ... END (with multiple WHEN) instead of the two IF
`
Check this here : http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html
But the COALESCE function can do the job for this case.
I might try something like this instead:
…
, COALESCE(NULLIF(actualDate, '1970-01-01'), CURRENT_TIMESTAMP()) AS actual_date
, NULLIF(actualDate <> '1970-01-01', false) AS is_real_date
…
Or maybe the second NULLIF() is not really necessary? Consider this:
…
, COALESCE(NULLIF(actualDate, '1970-01-01'), CURRENT_TIMESTAMP()) AS actual_date
, (actualDate <> '1970-01-01') AS is_real_date
…
The second column could then be true, false or NULL, and you could treat NULL same as false.
This is the most compact form I can think of using COALESCE and without repeating any comparison:
select id, type, real_date, if(real_date, actual_date, now()) as actual_date
from (
select *, coalesce(year(actual_date), 1970) != 1970 as real_date from table1
) as subResult
Working example