I've been looking over some code in an old Classic ASP system of ours that builds its own SQL within the stored procedure and then executes it {shudders}.
Several of the SELECTion lines contain an assignment, similar to:
SELECT
my_field = CASE WHEN value = whatever THEN 1 ELSE 0 END
...
Is there any difference (or anything I need to be aware of) between this and using a standard AS alias?...
SELECT
CASE WHEN value = whatever THEN 1 ELSE 0 END AS my_field
...
No, the following code is all synonymous:
SELECT one = 1;
SELECT 1 one;
SELECT 1 AS one;
SELECT 'one' = 1; --this is deprecated, don't use it.
Which you use (apart from the last), is normally down the preference. Personally, I use AS. One reason is I can then easily tell queries that return datasets, and those that assign values to variables a part.
The 2 examples that you have given are identical. However, when you go through the old code you might also find a variant with an # sign before my_field, like this:
SELECT
#my_field = CASE WHEN value = whatever THEN 1 ELSE 0 END
In this case a varable called #my_field is assigned a value, but nothing is SELECTed. This you can not rewrite to the other syntax using AS #myfield.
Related
I wasn't really sure of the best wording for the question but here is my dilemma:
I am passing a value to a sql query as #district. This value may be the exact district but it also has the possibility of being a value that should create a set of multiple districts. So if I pass 002 I want the WHERE clause to say I.Offense_Tract = #district. If I pass Other I want the WHERE clause to say I.Offense_Tract in (). What I am trying to do is something like:
AND
CASE
WHEN #district = "Other" THEN I.Offense_Tract in ('BAR','COL','GER','MEM','MIL','JAIL','JAILEAST','SCCC','1USD','2USD')
ELSE I.Offense_Tract = #district
END
But this doesn't work. The problem, restated, is if the value passed is anything other than Other, I just want it to be =. If Other is passed, I want it to be IN.
You don't need the CASE expression.
You can apply this logic with operators AND and OR:
AND (
(#district = 'Other' AND I.Offense_Tract IN ('BAR','COL','GER','MEM','MIL','JAIL','JAILEAST','SCCC','1USD','2USD'))
OR
(#district <> 'Other' AND I.Offense_Tract = #district)
)
Note that, in databases like MySql, Postgresql and SQLite, your code would work as it is.
The goal is simply to check whether a field is NULL or not, yielding a value of 1 when the field is not NULL, and 0 otherwise. I can't use COALESCE here, because if the field isn't NULL, I just want to return 1, not the value of the field.
I have a gut feeling that there's already a function that does this - something like NULL_STATUS_INTEGER(foo.bar), for example - instead of needing to write out the full CASE statement of CASE WHEN foo.bar IS NULL THEN 0 ELSE 1 END. I'm not saying that the CASE version is absurdly long, but I just find it strange that there's not a shorter way to do this.
I'm primarily interested in solutions that aren't confined to one SQL vendor, but I happen to be using SAS, if there happens to be a SAS-specific way to do this in PROC SQL.
Comparisons are also boolean, return a true/false
proc sql;
create table want as
select *, name = 'Alfred' as flag
from sashelp.class;
quit;
data want;
set sashelp.class;
flag = (name = 'Alfred');
run;
EDIT:
Another option is to use IFN()/IFC(), which factor in three conditions, FALSE, TRUE, MISSING. IFN()/IFC() can be used in SQL or a data step in SAS.
x = ifc(name="Alfred", 1, 0, .);
I have a really big stored procedure and I'd like to include a WHERE clause at the end to be executed just in case that #myparameter=1. I don't want the stored procedure to pay any attention to the WHERE clause when #myparameter=0. Is there any way to do this with CASE or something like that?
WHERE #myparameter=0 OR (insert the current conditions here)
add a modified version of where instead of yours
where (#myparemeter = 0 or (#myparameter = 1 and (your where conditions here)))
If you really want to use CASE, something like this ...
WHERE
CASE
WHEN (#myparameter=0) THEN 1
WHEN (#myparameter=1) AND (rest of where clause) THEN 1
ELSE 0
END = 1
MOVE "Y" TO :LKG-RETURN
EXEC SQL
SELECT "N"
INTO :LKG-RETURN
FROM SOME_TABLE
WHERE SOME_COLUMN = :SOME_VAR
END-EXEC.
This is a part of a SQLCOBOL program where I need to check some variable in a database to see if the main program must run or not a job. By default I put "Y" into the return value but if the select return lines the job must not be run, so I put "N" into it. My question is:
If the select return 0 lines (which mean the job must be run), does it still move "N" to :LKG-RETURN? If it does, what could be my options to achieve the desired result?
Thanks.
The normal SQL behaviour would be that the value is NOT returned. but I've never used SQLCOBOL to be able to test this. And whenever I have even the remotest hesitation, I test.
In the absence of the ability to test, this will always return a value...
SELECT COUNT(*)
INTO :LKG-RETURN
FROM SOME_TABLE
WHERE SOME_COLUMN = :SOME_VAR
-- 0 = no hits
Or possibly...
SELECT
CASE WHEN EXISTS (SELECT * FROM SOME_TABLE WHERE SOME_COLUMN = :SOME_VAR)
THEN 'Y' ELSE 'N' END
But, seriously, you need to find a way to test developments in your work environment.
I do not envy how difficult it must be where you work. I hope this works out for you.
I have been assigned the task of updating the EEO survey and reporting for a mid sized company. I am working on a stored procedure to populate a report from. All is good but for a syntax problem. One of the requirements is to dynamically allow the user to filter the results by the EEO Job Group Number. When the report page loads, it populates the table with all Job Groups Combined. I have placed a DropDownList on the page that allows the user to choose one of the 10 EEO Job Groups or by default, All Job Groups Combined (no filtering). The DDL executes postback and populates a parameter; #intEeoJobGroupID. There is not actually a 0 ID value in the table, just in the DDL. I want the (usp) query to use one set of WHERE statements if the passed parameter #intEeoJobGroupID = 0, and another if #intEeoJobGroupID <> 0. (Effectively adding another AND statement if the parameter <> 0)
I want to return the count of how many EEO records meet the requirements of the query. I have tried IF/THEN, and CASE, in many different formats, and can not seem get the syntax right. In the example below I get the message "Incorrect Syntax near the first = in the THEN statement, as well as the keyword ELSE.
Any hints?
DECLARE #intEeoJobGroupID INT
SELECT
COUNT (E.intEeoID)
FROM
dbo.NewEEO AS E
WHERE
CASE WHEN #intEeoJobGroupID = 0
THEN
E.intGenderID = 1
AND E.intRaceID = 2
ELSE
E.intGenderID = 1
AND E.intRaceID = 2
AND E.intEeoJobGroupID = #intEeoJobGroupID
You're making it way too complicated:
WHERE E.intGenderID = 1
AND E.intRaceID = 2
AND (E.intEeoJobGroupID = #intEeoJobGroupID OR #intEeoJobGroupID = 0)
As someone else already mentioned, your existing syntax was missing an "END", but it still won't work with that added. To get this right in the future, one thing you can try to do is remember that CASE expressions in SQL are just that: expressions. They are not statements, as you might be used to with if statements in c# code. You don't use CASE for flow control, to define blocks as you were trying to do.
Don't try to return a boolean from a CASE statement. Instead return some value that is then checked outside the CASE statement (and so then resulting in a boolean).
CASE WHEN #mode = 1 THEN CASE WHEN <Condition1> THEN 1 ELSE 0 END
WHEN #mode = 2 THEN CASE WHEN <Condition2> THEN 1 ELSE 0 END
END
=
1
Note: This will create Awful execution/explain plans and totally nerf performance. You are better using real IF blocks and real queries, or possibly unions...
IF #mode = 1
SELECT foo FROM bar WHERE <Condition1>
ELSE IF #mode = 2
SELECT foo FROM bar WHERE <Condition2>
Or...
SELECT foo FROM bar WHERE <condition1> AND #mode = 1
UNION ALL
SELECT foo FROM bar WHERE <condition2> AND #mode = 2
In order to prevent massive duplication of code, you may find that encapsulating the bulk of the query in a VIEW is helpful.
You can't make a comparison the result of a case condition. If you're using case in a where clause, it needs to be on one side of the operator:
CASE #case_value
WHEN 0 THEN
some_column
ELSE
some_other_column
END = #some_value
However, if you try to make your actual condition fit this rule, you'll end up not using the case statement at all, as #Joel point out.
You have to add
end
in the end of case.