case statement in where condition - sql-server-2012

In below script,it is showing 'Incorrect syntax near the keyword 'LIKE''.i am using CASE statement for checking length of F_TEXT_CODE>10. IF it is length>10 then i am using like operator if it is less than 10 i am using '=' operator.
how to achieve this logic in where condition?.
DECLARE
#MANU NVARCHAR(4000)='MANU0071'
BEGIN
SELECT TOP 1000 TP.F_PRODUCT AS ID,
TP.F_PRODUCT_NAME AS NAME
FROM PDF_DETAILS TP
LEFT JOIN V_PROD_ALIAS_MANU MAN ON MAN.F_PRODUCT = TP.F_PRODUCT
WHERE TP.F_PRODUCT<>''AND
(CASE WHEN LEN(MAN.F_TEXT_CODE)>10 THEN
(MAN.F_TEXT_CODE) LIKE #MANU
ELSE MAN.F_TEXT_CODE = #MANU END) AND
(TP.F_CUSTOM5 IS NULL OR TP.F_CUSTOM5 = '')
END

You can't use case like that.
case is an expression that returns a scalar value based on condition(s).
It can't be used as a flow-control element.
The logic you are describing can be accomplished using a combination of or and and:
DECLARE #MANU NVARCHAR(4000)='MANU0071'
BEGIN
SELECT TOP 1000 TP.F_PRODUCT AS ID,
TP.F_PRODUCT_NAME AS NAME
FROM PDF_DETAILS TP
LEFT JOIN V_PROD_ALIAS_MANU MAN ON MAN.F_PRODUCT = TP.F_PRODUCT
WHERE TP.F_PRODUCT<>''
AND
(
(LEN(MAN.F_TEXT_CODE)>10 AND MAN.F_TEXT_CODE LIKE #MANU)
OR
(LEN(MAN.F_TEXT_CODE)<=10 AND MAN.F_TEXT_CODE = #MANU)
)
AND
(TP.F_CUSTOM5 IS NULL OR TP.F_CUSTOM5 = '')
END
However, please note that using like without any wildcards will return the same result as using =, so the entire thing can be written like this
DECLARE #MANU NVARCHAR(4000)='MANU0071'
BEGIN
SELECT TOP 1000 TP.F_PRODUCT AS ID,
TP.F_PRODUCT_NAME AS NAME
FROM PDF_DETAILS TP
LEFT JOIN V_PROD_ALIAS_MANU MAN ON MAN.F_PRODUCT = TP.F_PRODUCT
WHERE TP.F_PRODUCT<>''
AND
AND MAN.F_TEXT_CODE = #MANU
AND
(TP.F_CUSTOM5 IS NULL OR TP.F_CUSTOM5 = '')
END:

Related

Attempting to use result of Case Expression in a join .. need to improve query

I have the following query which allows me to join the TransactionClass tables base on TransactionClassID from either the primary table (Transactions) or TransactionRules based on a condition as below:
SELECT
Description,
TC.Name,
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END) As ClassId
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId =
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionClassId
ELSE T.TransactionClassId
END)
The query is running on SQL Server,
In effect, it retrieves the correct TransactionClass entry depending on whether or not the join on TransactionRules was successful or not.
The above query works, but I am trying to simplify the query so that I do not have to repeat the CASE expression in two places.
I attempted to capture the result of the case expression in a variable and use that as follows:
SELECT
Description,
x
FROM Transactions AS T
LEFT JOIN TransactionRules TR
ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC
ON TC.TransactionClassId = x
WHERE x = (CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END)
But I get the error:
[S0001][207] Line 8: Invalid column name 'x'.
Where am I going wrong in my attempt to have only one CASE Expression?
CROSS APPLY is a tidy way to reuse a calculated value e.g.
SELECT
[Description]
, TC.[Name]
, Class.Id
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.[Description] LIKE TR.Pattern
CROSS APPLY (
VALUES (
CASE
WHEN TR.TransactionRuleId > 0
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END
)
) AS Class (Id)
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId = Class.Id;

SQL case when - create new variable

**QUESTION:
Is it possible to write a SQL statement where I create a new variable 'ART2' that solves:
if holdid <> stamholdid then Art = Art where holdid = stamholdid
I guess it is some form of 'case when'-statement
I have the following SQL:**
select ua.betegnelse as ART, ut.betegnelse as TYPE, rh.stamholdnr, rh.holdnr, rh.stamholdid, rh.holdid,
rh.produkt
from rpthold rh
INNER JOIN produkt p on p.id=rh.produktid
INNER JOIN UddannelseType ut on p.UddannelsesTypeID=ut.id
INNER JOIN UddannelseArt ua on ut.UddannelseArtID=ua.id
Where
rh.stamprodukt like '3.58'
and rh.stamholdnr like '21.06%'
and Year(rh.startdato) = '2021'
Best regards
Malene
You have "case when" with if functions:
SELECT
IF (
<some_condition>,
CASE
WHEN <CONDITION>
THEN <value>
WHEN <OTHER_CONDITION>
THEN <other_value>
END,
<default_value>
) as name_field
FROM...
You can use CASE..WHEN as follows:
case when rh.stamholdid = rh.holdid then 'Art - or whatever value you need'
else 'value you want if both are not equal'
end as art2

how to use LIKE instead of IN with multiple values?

I want to replace In with Like to make the query work.
SELECT
1 AS coddit, COD_CAT AS cam_cod, DES_CAT AS cam_desc,
LIVELLO_CAT AS livello, COD_CAT_PADRE AS cat_padre,
COD_L1, COD_L2, COD_L3, COD_L4, COD_L5, COD_L6
FROM
dbo.CLASS_ART
WHERE
1=1
AND TIPO_CLASS = 16 --B2B
AND LIVELLO_CAT = '0'
AND COD_CAT IN (SELECT DISTINCT CAT_MERCE.COD_CAT
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002')
The comparison I would like to do with LIKE otherwise the query doesn't work well
the subquery returns more than one value and it is correct but if I use Like instead of IN I have this error message:
Query return more than 1 values
Using LIKE against a subquery that returns multiple records won't work. A solution would be to turn the IN condition to an EXISTS condition, like:
and exists (
select 1
from ART_LIST_PREZZI
inner join ART_ANA
on ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
inner join CAT_MERCE
on ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
and ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
where COD_CAT like '%' + CAT_MERCE.COD_CAT + '%'
)
Like has to be compared to a single string, so you need to set all your ids on a single string. You can do that using the for xml clause.
(SELECT DISTINCT CAST(CAT_MERCE.COD_CAT AS VARCHAR(32))
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH(''))
Now I would delimite your ids by commas, so you don't find false positives, and compare it using like.
AND
(SELECT DISTINCT ',' + CAST(CAT_MERCE.COD_CAT AS VARCHAR(32)) + ','
FROM ART_LIST_PREZZI
INNER JOIN ART_ANA ON ART_LIST_PREZZI.COD_ART = ART_ANA.COD_ART
INNER JOIN CAT_MERCE ON ART_ANA.COD_CAT = CAT_MERCE.COD_CAT
AND ART_LIST_PREZZI.COD_LIST = 'EXPORT_002'
FOR XML PATH('')) LIKE '%,' + COD_CAT + ',%'
This would work, and you would have changed your IN operator with a LIKE operator, but I don't see the point of it, its performance would be worse than your original query.
Use EXISTS:
EXISTS (SELECT 1
FROM ART_LIST_PREZZI LP JOIN
ART_ANA A
ON LP.COD_ART = A.COD_ART JOIN
CAT_MERCE M
ON A.COD_CAT = M.COD_CAT AND
LP.COD_LIST = 'EXPORT_002' AND
CLASS_ART.COD_CAT LIKE M.COD_CAT
)
I assume that the logic you actually want uses wildcards:
CLASS_ART.COD_CAT LIKE CONCAT('%', M.COD_CAT, '%')
If so, it suggests an issue with the data model. Why would two columns with the same name (COD_CAT) need to be joined using LIKE instead of =.

Sql in sql server with convert

I am trying to use convert in an where clause in the select statement. My query looks like this:
SELECT DISTINCT TOP 10 [SurveyResult].*
,[Ticket].[RefNumber]
FROM [SurveyResult]
LEFT JOIN [Ticket] ON [SurveyResult].[TicketID] = [Ticket].[TicketID]
JOIN [SurveyResponse] AS SurveyResponse1 ON [SurveyResult].[ResultID] = SurveyResponse1.[ResultID]
JOIN [QuestionAnswer] AS QuestionAnswer1 ON SurveyResponse1.[AnswerID] = QuestionAnswer1.[AnswerID]
JOIN [SurveyQuestion] AS SurveyQuestion1 ON QuestionAnswer1.[QuestionID] = SurveyQuestion1.[QuestionID]
WHERE SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CONVERT(INT, SurveyResponse1.[Response]) >= 1
AND CONVERT(INT, SurveyResponse1.[Response]) <= 5
The problem is that I get some errors when converting the values to integer in the where statement.
I know I have some rows that don't contain numbers in the Response column but I filter those so without the convert part in the where clause I get only numbers so it works like this:
SELECT TOP 1000 [ResponseID]
,[ResultID]
,[Response]
FROM [WFSupport].[dbo].[SurveyResponse]
JOIN QuestionAnswer ON SurveyResponse.AnswerID = QuestionAnswer.AnswerID
WHERE QuestionAnswer.QuestionID = 'C10BF42E-5D51-46BC-AD89-E57BA80EECFD'
And in the results I get numbers but once I add the convert part in the statement I I get an error that it can't convert some text to numbers.
Either do like Mark says or just have NULL values default to something numerical, this would give you a where statement like:
WHERE SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CONVERT(INT, ISNULL(SurveyResponse1.[Response],0)) BETWEEN 1 AND 5
The important part is the ISNULL() function and I also used BETWEEN to avoid duplicate converts.
Try:
SELECT DISTINCT TOP 10
[SurveyResult].*,
[Ticket].[RefNumber]
FROM
[SurveyResult]
LEFT JOIN [Ticket] ON [SurveyResult].[TicketID] = [Ticket].[TicketID]
JOIN [SurveyResponse] AS SurveyResponse1
ON [SurveyResult].[ResultID] = SurveyResponse1.[ResultID]
JOIN [QuestionAnswer] AS QuestionAnswer1
ON SurveyResponse1.[AnswerID] = QuestionAnswer1.[AnswerID]
JOIN [SurveyQuestion] AS SurveyQuestion1
ON QuestionAnswer1.[QuestionID] = SurveyQuestion1.[QuestionID]
where SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CASE SurveyQuestion1.[QuestionID]
WHEN 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
THEN Convert(int, SurveyResponse1.[Response])
ELSE 0
END BETWEEN 1 AND 5
(The AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016' is retained in case the query is using an index on QuestionID - if not, it can be removed, as the same condition is implicit in the subsequent CASE condition.)
Try this one -
SELECT DISTINCT TOP 10 sr.*, t.[RefNumber]
FROM dbo.SurveyResult sr
JOIN dbo.SurveyResponse sr2 ON sr.[ResultID] = sr2.[ResultID]
JOIN dbo.QuestionAnswer sa ON sr2.[AnswerID] = sa.[AnswerID]
JOIN dbo.SurveyQuestion sq ON sa.[QuestionID] = sq.[QuestionID] AND sq.[SurveyID] = sr.[SurveyID]
LEFT JOIN dbo.Ticket t ON sr.[TicketID] = t.[TicketID]
WHERE sq.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CAST(ISNULL(sr2.[Response], 0) AS INT) BETWEEN 1 AND 5

Trouble with case statement

I am having problems with this case statement. I don't know what I am doing wrong but I get the error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I have a case when the field equals a value then do a left outer join but if the field equals a different value then do a inner join.
This is my query:
SELECT
case
when oqt = '26' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt)and active = 1)
END,
case
when oqt = '31' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM inner join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
where QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt) and active = 1)
END
from tempoq
The case is an expression that must evaluate to a value. The Select statements that you have return multiple values.
It would seem that you're trying to use Case like it's a C# switch? If that's the case, then you're likely better off with an IF ELSE IF construction.
It looks like you want to do something like this rather than using a CASE statement.
DECLARE #t int
-- This would contain your oqt value
SET #t =1
IF #t = 1
BEGIN
SELECT * FROM tableA
END
ELSE IF #t = 2
BEGIN
SELECT * FROM TableB
END
Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM
inner join tempoq on tempoq.oqt = QM.id_oqt
left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE active = 1 and (tempoq.oqt = '26' or (tempoq.oqt = '31' and courseversions.* is not null))
left outer join means join OQMethods's data which even no match data from courseversions,
then filter the data with null courseversions.* that is inner join.
Hope I have the right understanding.