MS-Access query to T-SQL [duplicate] - sql-server

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
CASE equivalent of a nested IIF statement
I'm trying to convert the following Access query into T-SQL, but I'm having problems with IIF statement.
ACCESS Query
SELECT
qry_LAB_LOAD_Prequery2.Asset AS SITE_REF,
Format([Det],"00000") AS DET_,
IIf(IsNull([MT]),"0",IIf(Right([SP_Ref],2)="WZ"
And IsNull([LabLoadFileSuffix_MT])
And [MT]>0,CStr([MT]) & "CT",CStr([MT]) & [LabLoadFileSuffix_MT])) AS MT_COUNT,
IIf(IIf(IsNull([MT]),0,[MT])>=IIf(IsNull([IM]),0,[IM]),0,
IIf(IsNull([IM]),"0",IIf(Right([SP_Ref],2)="WZ"
And IsNull([LabLoadFileSuffix_IM]),CStr([IM])
& "CT",CStr([IM]) & [LabLoadFileSuffix_IM]))) AS IM_COUNT,
qry_LAB_LOAD_Prequery2.[2012 Sample Point] AS SP_REF, qry_LAB_LOAD_Prequery2.Area
FROM qry_LAB_LOAD_Prequery2
WHERE (((IIf(IsNull([IM]),0,[IM])+IIf(IsNull([MT]),0,[MT]))>0));
I've tried to convert a part of it. Can anyone help me correct the nested IID statement as I'm not sure.
SQL Query
SELECT qry_LAB_LOAD_Prequery2.Asset AS SITE_REF,
RIGHT('00000' + CAST([Det] AS VARCHAR(5)),5) AS DET_,
----- (the nested iff statements)
qry_LAB_LOAD_Prequery2.[2012 Sample Point] AS SP_REF,
qry_LAB_LOAD_Prequery2.Area
FROM qry_LAB_LOAD_Prequery2
where (ISNull([IM],0) + ISNULL([MT],0)) > 0

To convert the nested IIF you need user CASE.
Lets take the first one:
Reformating I get:
IIf(
IsNull([MT]),
"0",
IIf(Right([SP_Ref],2)="WZ"
And IsNull([LabLoadFileSuffix_MT])
And [MT]>0,
CStr([MT]) & "CT",
CStr([MT]) & [LabLoadFileSuffix_MT]
)
) AS MT_COUNT,
It Converts to :
CASE
WHEN [MT] IS NULL
THEN "0",
ELSE
CASE
WHEN Right([SP_Ref],2) = "WZ"
AND ([LabLoadFileSuffix_MT] IS NULL
AND [MT]>0
THEN
CAST([MT] AS VARCHAR) + "CT"
ELSE
CAST([MT] AS VARCHAR) + [LabLoadFileSuffix_MT]
END
END AS MT_COUNT,
Which simplifies to :
CASE
WHEN [MT] IS NULL
THEN "0",
ELSE
CAST([MT] AS VARCHAR)
+ CASE
WHEN Right([SP_Ref],2) = "WZ"
AND ([LabLoadFileSuffix_MT] IS NULL
AND [MT]>0
THEN
"CT"
ELSE
[LabLoadFileSuffix_MT]
END
END AS MT_COUNT,
For tee second one I reformatted and then converted it to the following
CASE WHEN
CASE
WHEN [MT] IS NULL THEN 0
ELSE [MT]
END
>=
CASE
WHEN [IM] IS NULL THEN 0
ELSE [IM]
END ,
THEN 0,
ELSE
CASE
WHEN [IM] IS NULL THEN "0"
ELSE
CASE
WHEN Right([SP_Ref],2) = "WZ" AND [LabLoadFileSuffix_IM] IS NULL THEN CAST([IM] AS VARCHAR) + "CT"
ELSE CAST([IM] AS VARCHAR) + [LabLoadFileSuffix_IM]
END
END
END
AS IM_COUNT,
Whick reduces to
CASE
WHEN ISNULL([MT], 0) > = ISNULL([IM], 0)
THEN 0,
ELSE
CASE
WHEN [IM] IS NULL THEN "0"
ELSE
CAST([IM] AS VARCHAR) +
CASE
WHEN Right([SP_Ref],2) = "WZ" AND [LabLoadFileSuffix_IM] IS NULL THEN "CT"
ELSE [LabLoadFileSuffix_IM]
END
END
END
AS IM_COUNT,
Which essentially boils down to 2 very similar expressions for both columns.

Try a nested case statement.
So just taking the first 2 of your lines:
IIf(IsNull([MT]),"0",IIf(Right([SP_Ref],2)="WZ"
And IsNull([LabLoadFileSuffix_MT])
would become
CASE WHEN MT IS NULL
THEN 0
ELSE
CASE WHEN RIGHT(SP_Ref, 2) = "WZ" AND LabLoadFileSuffix_MT IS NULL
THEN
...
ELSE ...
END
END

Related

SQL Server 2012 and NULL comparison

Can anyone explain me why these two statements returns different results?
SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END
SELECT CASE WHEN NOT((NULL = NULL) AND (1 != 1)) THEN 1 ELSE 0 END
I know that NULL compared with anything gives false and I wanted to use that property but I stopped at commands similar to above. My real statements instead of NULLs use variables that can be NULL but I simplified them to show where is the problem. I thought that it has something with operation order but it seems that's not it.
I know that NULL compared with anything gives false
This isn't correct, NULL compared with anything evaluates to unknown, not false, a quick example:
SELECT CASE WHEN (NULL = NULL) THEN 'True'
WHEN NOT(NULL = NULL) THEN 'False'
ELSE 'Other'
END
Will give the third option of Other.
If we rewrite your logic (still the same meaning, but it becomes more clear):
SELECT CASE WHEN (NULL <> NULL) AND (1 = 1) THEN 1 ELSE 0 END
SELECT CASE WHEN (NULL <> NULL) OR (1 = 1) THEN 1 ELSE 0 END
So in the first instance you have WHEN [Unknown] AND [True] which is false, but in the second you have WHEN [Unknown] OR [True] which is true, so returns 1.
If you rewrite the query with variables, then inspect the execution plan XML, you can see that SQL Server rewrites the expression as above during compilation:
DECLARE #a INT = NULL, #b INT = NULL, #c INT = 1, #d INT = 1;
SELECT TOP 1
CASE WHEN NOT((#a = #b) OR (#c != #d)) THEN 1 ELSE 0 END,
CASE WHEN NOT((#a = #b) AND (#c != #d)) THEN 1 ELSE 0 END
-- first query
SELECT CASE WHEN NOT((NULL = NULL) AND (1 != 1)) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown AND false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN true THEN 1 ELSE 0 END
=
1
-- second query
SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown OR false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown) THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown THEN 1 ELSE 0 END
=
else matched, so 0
And to D0dger's question from comments:
It's more interesting why SELECT CASE WHEN (NULL = NULL) OR (1 != 1) THEN 1 ELSE 0 END and SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END returns 0
SELECT CASE WHEN (NULL = NULL) OR (1 != 1) THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown OR false THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown THEN 1 ELSE 0 END
=
else matched, so 0
OR (Transact-SQL), AND (Transact-SQL)
So, there are 2 options: Either you have ANSI_NULLS ON (and you should) or you have ANSI_NULLS OFF.
In the first case, any comparison with NULL returns NULL (even comparisons between NULL values such as yours).
In the second case, sql server will evaluate comparisons between NULL values (e.g. NULL=NULL will return true).
So before considering the different results in your queries you must first consider that comparing NULL with anything, doesn't evaluate to false but NULL

Remove first leading 0 from varchar with MSSQL

How I can remove only the first 0 character from a varchar?
For example '000303' ==> '00303'
I tried this without success, all the 0 characters are removed:
SELECT SUBSTRING('000303', PATINDEX('%[^0]%', '000303'),LEN('000303'));
Thanks
Try using STUFF Function
SELECT CASE WHEN LEFT('000303',1) = '0' THEN STUFF('000303',1,1,'') ELSE '000303' END
or Use RIGHT Function
SELECT CASE WHEN LEFT('000303',1) = '0' THEN RIGHT('000303', LEN('000303')-1) ELSE '000303' END
Instead of LEFT('000303',1) = '0' check you can also use
charindex('0','000303') = 1 or
'000303' LIKE '0%' (ughai suggestion)
Try this:
SELECT RIGHT(MyColumn, LEN(MyColumn) - 1)
This will remove the first character from the varchar column.
If it is specific to 0 then try this:
SELECT CASE WHEN LEFT(MyColumn,1) = '0'
THEN RIGHT(MyColumn, LEN(MyColumn) - 1)
ELSE
MyColumn END
Something like
SELECT CASE WHEN LEFT(Mycol,1) = '0' THEN SUBSTRING(MyCOL, 2, LEN(MyCOL)) END

IIF to Case statement

I have the below code in Access which I'm migrating to SQL Server,
IIf([code] Is Not Null,IIf([code]<>'ABC',
IIf([length] Is Null,1,IIf([Length]=0,1,
IIf([width] Is Null,1,IIf([Width]=0,1,
IIf([height] Is Null,1,IIf([Height]=0,1,
0))))))))
I believe it checks for code not null and not equal to 'ABC' then length should be null or 0 then it assigns a value 1 of the condition fails then it is 0. I need a little help with writing it with case.
Literal translating:
CASE WHEN [code] Is Not Null
THEN
CASE WHEN [code]<>'ABC'
THEN
CASE WHEN [length] Is Null
THEN 1
ELSE
CASE WHEN [Length]=0
THEN 1
ELSE
CASE WHEN [width] Is Null
THEN 1
ELSE
CASE WHEN [Width]=0
THEN 1
ELSE
CASE WHEN [height] Is Null
THEN 1
ELSE
CASE WHEN [Height]=0
THEN 1
ELSE 0
END
END
END
END
END
END
END
END
Simplified in :
CASE WHEN ISNULL([code], 'ABC') <>'ABC' AND
(ISNULL([length], 0) = 0 OR
ISNULL([width], 0) = 0 OR
ISNULL([height], 0) = 0)
THEN 1
ELSE 0
END
IIf in JET SQL translates to CASE WHEN in SQL Server as follows:
IIf(condition, whenTrue, whenFalse)
translates directly to
CASE WHEN condition THEN whenTrue ELSE whenFalse END
For nested expressions
IIf(condition1, whenTrue1, IIf(condition2, whenTrue2, whenFalse))
you can either translate them directly:
CASE WHEN condition1
THEN whenTrue1
ELSE CASE WHEN condition2
THEN whenTrue2
ELSE whenFalse
END
END
or use the fact that CASE allows you to specify multiple WHEN conditions:
CASE WHEN condition1 THEN whenTrue1
WHEN condition2 THEN whenTrue2
ELSE whenFalse
END
With this knowledge, translating your statement should be easy and is left as an exercise to the reader (I don't want to spoil the fun).

'an expression of non boolean type specified' in CASE WHEN

Given this T-SQL code:
SELECT CASE
WHEN ( Cast (CASE
WHEN Isnull(bpe.new, 0) = 0
AND Isnull(bpe.regular, 0) = 0
AND Isnull(bpe.bargain, 0) = 0 THEN 0
ELSE 1
END AS BIT)
AND #siteID IS NULL
OR bpe.siteid = #siteID ) THEN 1
ELSE 0
END AS SiteHasBrandException
FROM brandpromoexceptions AS bpe
I get the error message:
an expression of non boolean type specified in the context where a condition is expected TSQL
Why is that?
If you mean zero as "false" for that first bit, the query should be equivalent to:
SELECT CASE WHEN
NOT ( ISNULL(bpe.new, 0) = 0
AND Isnull(bpe.regular, 0) = 0
AND Isnull(bpe.bargain, 0) = 0 )
AND ( #siteID IS NULL
OR bpe.siteid = #siteID )
THEN 1
ELSE 0
END AS SiteHasBrandException
FROM brandpromoexceptions AS bpe
You may need to be careful with that "OR" clause, or add parentheses for clarification. I guessed here.
You are passing your first CASE statement a call to CAST rather than a conditional. The error message pretty much spells it out.
I'm not sure exactly what you are trying to do, but you seem to understand that you need to pass a boolean to the CASE WHEN based on your subsequent use of CASE so hopefully this helps.
this is a shot in the dark by try changing your code to this:
SELECT CASE
WHEN ( Cast (CASE
WHEN Isnull(bpe.new, 0) = 0
AND Isnull(bpe.regular, 0) = 0
AND Isnull(bpe.bargain, 0) = 0 THEN 0
ELSE 1
END AS BIT) = 1
AND #siteID IS NULL
OR bpe.siteid = #siteID ) THEN 1
ELSE 0
END AS SiteHasBrandException
FROM brandpromoexceptions AS bpe

How do I put a CASE statement in a SUBSTRING statement?

The purpose of this that I'm trying to compare the usernames of two email addresses and see if they're the same. Really, all I want is for this to work.
When I run the query, all I get is: Invalid length parameter passed to the LEFT or SUBSTRING function.
Note: I changed the query. This better illustrates what I'm trying to do.
Note2: I've made the changes so it works properly, but now if the parameter is '', then I get: Invalid length parameter passed to the LEFT or SUBSTRING function.
declare #ReportParameter1 nvarchar(16)
set #ReportParameter1 = 'manmoon#test1.com'
declare #ReportParameter2 nvarchar(16)
set #ReportParameter2 = ''
select 'test'
where SUBSTRING (case #ReportParameter1 when '' then 'x#' else #ReportParameter1 end, 1, Charindex('#', case #ReportParameter1 when '' then 'x#' else #ReportParameter1 end) - 1) =
SUBSTRING (case #ReportParameter2 when '' then 'x#' else #ReportParameter2 end, 1, Charindex('#', case #ReportParameter2 when '' then 'x#' else #ReportParameter2 end) - 1)
Here's the where clause I used to fix the problem. However, this will teach me to be more careful when copying and pasting.
WHERE (substring(#ReportParameter1, 1, case when (CHARINDEX('#', #ReportParameter1) - 1) < 1 then 1 else CHARINDEX('#', #ReportParameter1) - 1 end) = SUBSTRING(#ReportParameter2, 1, CHARINDEX('#', #ReportParameter2) - 1))
The error comes from not comparing the result of the substring to anything. A string is not a boolean expression.
Edit:
Now that you edited your question, that answer doesn't make any sense any more.
I tested your substring expressions with empty strings, and I don't get any error. If you on the other hand have strings that are not empty, but doesn't contain any # character, then you get the error that you describe.
To handle that you could do like this:
... where case
when #ReportParameter1 = '' or charindex('#', #ReportParameter1) = 0 then 'x'
else substring(#ReportParameter1, 1, charindex('#', #ReportParameter1) - 1)
end =
case
when #ReportParameter2 = '' or charindex('#', #ReportParameter2) = 0 then 'x'
else substring(#ReportParameter2, 1, charindex('#', #ReportParameter2) - 1)
end
Note however that two strings that are not email addresses would compare as equal, as 'x' = 'x', so you might want to use different fallback values in the expressions...
Edit 2:
Come to think of it, you don't need to check for empty strings if you check for the # character, as an empty string can't contain a # character:
... where case
when charindex('#', #ReportParameter1) = 0 then 'x'
else substring(#ReportParameter1, 1, charindex('#', #ReportParameter1) - 1)
end =
case
when charindex('#', #ReportParameter2) = 0 then 'x'
else substring(#ReportParameter2, 1, charindex('#', #ReportParameter2) - 1)
end
put the substring in the case... you basically want a static value on one case... on the other ... use the substring on the "else"
case GPS_Quotes.[Sales Engineer]
when
'' then 'some constant value'
else
substring(GPS_Quotes.[Sales Engineer], 1, ...{I don't understand what your are trying to do})
end

Resources