Convert IIF() Access statement to SQL Server - sql-server

I am trying to convert a access code into sql 2008. But just found out sql 2008 doesn't support the IIF statement! Here are two ways that I am trying to rewrite my query, I know I am messing up with the syntax:
select distinct (IIf(IsNull([dbo_TASK]![act_start_date])
,IIf(IsNull([dbo_TASK]![restart_date]),[dbo_TASK]![target_start_date],[dbo_TASK]![restart_date]),[dbo_TASK]![act_start_date]) AS [Estimated Start Date] from dbo.task
ATTEMPT1:
if dbo.task.act_start_date=null
then
if(dbo.task.restart_date=null)
then dbo.task.target_start_date
else dbo.task.restart_date
else dbo.task.act_start_date
ATTEMP2:
select (case when dbo.task.act_start=null then
(case when dbo.task.restart_date=null
then (dbo.task.target_start_date)
else dbo.task.restart_date
end)
else (dbo.task.act_start_date)
end) from dbo.task

Your query was very close. When checking if a value is equal to null you use Is Null not =null
So if you implement that you can use the following:
select distinct
case
when [act_start_date] is null
then
case
when [restart_date] is null
then [target_start_date]
else [restart_date]
else [act_start_date]
end AS [Estimated Start Date]
from dbo.task
Or even easier you can use COALESCE() which will return the first non-null value:
select distinct
coalesce([act_start_date], [restart_date], [target_start_date]) as [Estimated Start Date]
from dbo.task

Related

How to get the latest not null value from multiple columns in SQL or Azure Synapse

I have data like in the below format
I want output in the below format
Please help me with the SQL code. Thanks !
Like I mention in the comments, you need to fix whatever it is that's inserting the data and not lose the values so that they become NULL in "newer" rows.
To get the results you want, you'll going to have to use row numbering and conditional aggregation, which is going to get messy the more columns you have; and why you need to fix the real problem. This will look something like this:
WITH CTE AS(
SELECT GroupingColumn,
NullableCol1,
NullableCol2,
DateColumn,
CASE WHEN NullableCol1 IS NOT NULL THEN ROW_NUMBER() OVER (PARTITION BY GroupingColumn, CASE WHEN NullableCol1 IS NULL THEN 1 ELSE 0 END ORDER BY DateColumn DESC) AS NullableCol1RN,
CASE WHEN NullableCol2 IS NOT NULL THEN ROW_NUMBER() OVER (PARTITION BY GroupingColumn, CASE WHEN NullableCol2 IS NULL THEN 1 ELSE 0 END ORDER BY DateColumn DESC) AS NullableCol2RN
FROM dbo.YourTable)
SELECT GroupingColumn,
MAX(CASE NullableCol1RN WHEN 1 THEN NullableCol1 END) AS NullableCol1,
MAX(CASE NullableCol2RN WHEN 1 THEN NullableCol2 END) AS NullableCol2,
MAX(DateColumn) AS DateColumn
FROM CTE;

SQL Server Nested CASE and OR in WHERE statement

I have been trying all day to figure out how to (properly) move a nested IIF statement from Access to SQL Server.
The query needs to evaluate a simple NULL/-1/1 (null/yes/no) combobox. If it is blank, it should bring back all records. If YES (-1) then return Demog.[LT Due Date] <= GETDATE(). If NO (1) then Demog.[LT Due Date] >= GETDATE().
Here is the ACCESS SQL that works perfectly:
SELECT Demog.ID, Demog.[Long Term Date]
FROM Demog
WHERE (
(iif(Forms!Demog_Entry!cbox_LTPD=-1,Demog.[Long Term Date]<=Date(),
(iif(Forms!Demog_Entry!cbox_LTPD=0,Demog.[Long Term
Date]>=Date(),isnull(Forms!Demog_Entry!cbox_LTPD))))));
And here is one of the SQL Server Codes I've tried: It evaluates the Null correctly, but if anything else it only returns Demog.[LT Due Date] <= GETDATE().
Declare #LTPD as Bit
Set #LTPD = -1
SELECT Demog.ID, Demog.[LT Due Date]
FROM Demog
WHERE (1=(CASE WHEN #LTPD Is Null THEN 1 ELSE 0 END) OR Demog.[LT Due Date] <= GETDATE())
I have also tried doing a combination of CASE and OR statements. Here is what I have, but again, I just can't get it to evaluate all 3 states correctly.
WHERE (1=(CASE WHEN #LTPD Is Null THEN 1 ELSE 0 END) OR
(#LTPD=-1 AND Demog.[LT Due Date] <= GETDATE()) OR
(#LTPD=1 AND Demog.[LT Due Date] >= GETDATE()))
I also tried using IIF but could not make it work no matter what I did. I'm assuming IIF works in the SELECT statement but not the WHERE statement?
you might just need some ORs
select Demog.ID, Demog.[Long Term Date]
from Demog
where (#LTPD IS NULL)
or (#LTPD = -1 AND Demog.[Long Term Date]<=GetDate())
or (#LTPD = 1 AND Demog.[Long Term Date]>=GetDate())

Can i use a case statement to convert a varchar to decimal and use that in my where clause?

I have a column which I want to convert to decimal so I can then use it to compare in my where clause. I want to make sure all values from the column are greater or equal to 1.3. I converted the column successfully in the select statement but when attempting to do the same convert in the where clause I get the following error:
Arithmetic overflow error converting varchar to data type numeric.
I am using SQL Server 2008.
SELECT ID,
CASE
WHEN ISNUMERIC(USER_3) = 1
THEN Convert(varchar(50), CONVERT(decimal(14,2), USER_3))
END AS KG_M
FROM PART
WHERE USER_3 IS NOT NULL
AND CASE
WHEN ISNUMERIC(USER_3) = 1
THEN Convert(varchar(50), CONVERT(decimal(14,2), USER_3))
END >= 1.3
Sure, why not? Here's a self-contained example:
select a.ID
, b.KG_M
from (values
(1, N'12345678')
, (2, N'ABCDEFGH')
) as a (ID, USER_3)
cross apply (values(
case IsNumeric(a.USER_3)
when 1 then Convert(varchar(50), Convert(decimal(14, 2), a.USER_3))
else a.USER_3
end
)) as b (KG_M)
where b.KG_M >= '1.3';
We simply use the APPLY operator to contain our calculation for reuse later.
You need to choose one way to convert. I would use the native type for comparison, decimal.
SELECT * FROM
(
SELECT ID, KG_M=CAST(USER_3 AS decimal(14,2))
FROM PART
WHERE
ISNUMERIC(USER_3) = 1
)AS X
WHERE
X.KG_M >= 1.3
Allow strings that are not numbers in outoput
SELECT * FROM
(
SELECT
ID,
USER_3_AsDecimal=CASE WHEN ISNUMERIC(USER_3) THEN CAST(USER_3 AS decimal(14,2)) ELSE NULL END,
USER_3
FROM PART
WHERE
NOT USER_3 IS NULL
)AS X
WHERE
X.USER_3_AsDecimal IS NULL
OR
X.USER_3_AsDecimal >= 1.3
The problem was a syntax error, the case in the where clause was a success the entire time.
"you should use >= '1.3' since you are converting to varchar" credit to #Lamak in comments

how to order list that has date and a word in sql server

case when prefinallist.truckbooked is null then 'Immediate' else CAST(prefinallist.previous_date as varchar) END as ETA
The list contain either the word Immediate or datetime.
How to show immediate on the top and date in acending.
You can try to use ORDER BY like this:
ORDER BY (`ETA` = 'Immediate') ASC
or you can also use CASE statement inside the ORDER BY like
ORDER BY CASE WHEN ETA = 'Immediate' THEN 1 ELSE 2 END

Iff condition Access to SQL syntax

I have an access query that I have recreate in SQL.
Access:
SELECT Columns ,
IIf([Col1]="X",IIf([COL2]<>"XXXX",1,0)) AS NEWCOL1,
IIf([COL2] Not In ("HHH","GGG"),1,0) AS [NEWCOL2],
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM [TABLE]
WHERE ((([TABLE].COL2)<>"XXXX")) OR ((([TABLE].COL2)<>"HHH" And ([TABLE].COL2)<>"GGG"));
In SQL :
SELECT Columns ,
"NEWCOL1" =
CASE WHEN ([COL1]='X' AND COL2<> 'XXXX') THEN 1
ELSE 0
END,
"NEWCOL2" =
CASE WHEN COL2 NOT IN ('HHH','GGG') THEN 1
ELSE 0
END ,
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM [TABLE]
WHERE ((([TABLE].COL2)<>'XXXX')) OR ((([TABLE].COL2)<>'HHH' And ([TABLE].COL2)<>'GGG'));
IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
When I use the Newcol1 and newcol2 it throws an error invalid column how could use them maybe in a nested case or iif statement
If you're in SQL 2012, where IIF() is valid, then it looks like the problem is that you don't have an ELSE value for the first outer case:
IIf([Col1]='X',IIf([COL2]<>'XXXX',1,0){,NEED SOME ELSE VALUE HERE}) AS NEWCOL1,
I don't know why this would work in Access. I guess Access must be more "dummy proof" than SQL Server.
To replace your original first IIF with a CASE, you would do this:
CASE WHEN [Col1]='X' THEN
CASE WHEN [COL2]<>'XXXX' THEN 1 ELSE 0 END
END
By not supplying an ELSE for the first condition, if [Col1] does not equal 'X', the statement will return NULL without raising an error.
To handle your most recent request with a CTE, you could do as below:
WITH cte AS (
SELECT
Columns,
CASE WHEN ([COL1]='X' AND COL2<> 'XXXX') THEN 1 ELSE 0 END AS NEWCOL1,
CASE WHEN COL2 NOT IN ('HHH','GGG') THEN 1 ELSE 0 END AS NEWCOL2
FROM [TABLE]
WHERE ((([TABLE].COL2)<>'XXXX')) OR ((([TABLE].COL2)<>'HHH' And ([TABLE].COL2)<>'GGG'))
)
SELECT *, IIf(([NEWCOL1]=1) Or ([NEWCOL2]=1),1,0) AS NEWCOL3
FROM cte;

Resources