Y or N in an SQL result - sql

Is there a way to have a query return either a 'Y' or 'N' for a column if that column has a value above a certain number say '25'.
I am using DB2 on ZOS

SELECT CASE WHEN Col1 > 25 THEN 'Y' ELSE 'N' END As Value1
FROM Table1

For MySQL:
SELECT IF(column > 25, 'Y', 'N')
FROM table
http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_if

There is a IF block for SQL.
http://sqltutorials.blogspot.com/2007/06/sql-ifelse-statement.html

Use the SQL CASE statement

SELECT CASE WHERE columnname > 25 THEN 'Y' ELSE 'N' END FROM table;

select
case when somecolumn > 25 then 'Y' else 'N' end as somename
from sometable;

Select If(myColumn > 25, 'Y', 'N') From myTable

Apart from the IF and CASE statements another valid alternative is to create a user defined function feeding in your column value and returning Y or N.
This has the not inconsiderable advantage that if you are selecting on this criteria in more than on SQL statement and at a later date your condition changes - to over 30 say - then you have only one place to change your code. Although using a function adds complexity and overhead so is not always optimal don't underestimate the maintenance advantage of this approach. A minor plus too is you can make the name of the function something more meaningful, and hence self documenting, than an inline CASE

Related

Invalid argument for function integer IBM DB2

I need to filter out rows in table where numer_lini column has number in it and it is between 100 and 999, below code works just fine when i comment out line where i cast marsnr to integer. However when i try to use it i get error: Invalid character found in a character string argument of the function "INTEGER". when looking at the list seems like replace and translate filters only numbers just fine and select only contains legit numbers (list of unique values is not long so its easy to scan by eye). So why does it fail to cast something? I also tried using integer(marsnr), but it produces the same error. I need casting because i need numeric range, otherwise i get results like 7,80 and so on. As I mentioned Im using IBM DB2 database.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where numer_lini in (
select marsnr
from (
select
distinct numer_lini marsnr
from alaska.trasa
where case
when replace(translate(numer_lini, '0','123456789','0'),'0','') = ''
then numer_lini
else 'no'
end <> 'no'
)
where cast(marsnr as integer) between 100 and 999
)
fetch first 300 rows only
If you look at the optimized SQL from the Db2 explain, you will see that Db2 has collapsed your code into a single select.
SELECT DISTINCT Q2.NUMER_LINI AS "NUMER_LINI",
Q2.WAR_TRASY AS "WAR_TRASY",
Q2.ID_PRZ1 AS "ID_PRZ1",
Q2.ID_PRZ2 AS "ID_PRZ2",
Q1.NUMER_LINI
FROM ALASKA.TRASA AS Q1,
ALASKA.TRASA AS Q2
WHERE (Q2.NUMER_LINI = Q1.NUMER_LINI)
AND (100 <= INTEGER(Q1.NUMER_LINI))
AND (INTEGER(Q1.NUMER_LINI) <= 999)
AND (CASE WHEN (REPLACE(TRANSLATE(Q1.NUMER_LINI,
'0',
'123456789',
'0'),
'0',
'') = '') THEN Q1.NUMER_LINI
ELSE 'no' END <> 'no')
Use a CASE to force Db2 to do the "is integer" check first. Also, you don't check for the empty string.
E.g. with this table and data
‪create‬‎ ‪TABLE‬‎ ‪alaska‬‎.‪trasa‬‎ ‪‬‎(‪numer_lini‬‎ ‪VARCHAR‬‎(‪10‬‎)‪‬‎,‪‬‎ ‪war_trasy‬‎ ‪INT‬‎ ‪‬‎,‪‬‎ ‪id_prz1‬‎ ‪INT‬‎,‪‬‎ ‪id_prz2‬‎ ‪INT‬‎)‪;
insert into alaska.trasa values ('',1,1,1),('99',1,1,1),('500',1,1,1),('3000',1,1,1),('00300',1,1,1),('AXS',1,1,1);
This SQL works
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when translate(numer_lini, '','0123456789') = ''
and numer_lini <> ''
then integer(numer_lini) else 0 end
between 100 and 999
Although that does fail if there is an embedded space in the input. E.g. '30 0'. To cater for that, a regular expressing is probably preferred. E.g.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when regexp_like(numer_lini, '^\s*[+-]?\s*((\d+\.?\d*)|(\d*\.?\d+))\s*$'))
then integer(numer_lini) else 0 end
between 100 and 999

SQL Server: interpreting 'y' as BIT value

In C, when you compared true/false value to 1/0, it worked very well.
I would want the similar possibility with SQL Server - when I have a bit column, I would like to compare myBitField = 'y' / myBitField = 'n'
Is there anything I can do about that? Maybe change some SQL interpreter settings or something?
Example of what I would like to do:
select * from
(
select CAST(1 AS BIT) as result
) as main
where main.result = 'y'
Currently, it throws an error, and I would like it to return 1/true/'y', whatever, but I would like it to be able to make that comparison.
I suppose you want to do it for some yes/no thing. But this is generally a wrong concept, your application which is accessing the SQL Server should interpret y as a 1 and n as a 0 and afterwards set the correct parameters for the query. You should not (actually I'm temped to write "must not") do this in SQL Server, that's what you have a business logic for.
As others have said, BIT and CHAR / VARCHAR are entirely different datatypes. But if you want to cast them during the select, you can use CASE expression like so:
-- Reading string as BIT
SELECT CAST(CASE RESULT WHEN 'Y' THEN 1 WHEN 'N' THEN 0 ELSE NULL END AS BIT) RESULT
-- Reading BIT as string
SELECT CAST(CASE RESULT WHEN 1 THEN 'Y' WHEN 0 THEN 'N' ELSE NULL END AS CHAR(1)) RESULT
And that's about as far as your options go here, far as I can understand. :)

Return 'Yes' or No' from select statement?

tbl_LoanSummary has Sample_Number column. I have to check if Sample_Number column is not null the return 'Y' otherwise return return 'N' from below select statement.
select a.Br_Loan_No ,a.Br_LookupKey, //return IsNull(s.Sample_Number) ='N' or 'Y'
from dbo.tbl_Br a left outer join dbo.tbl_LoanSummary s
on s.Loan_no = a.Br_Loan_No order by a.Br_Loan_No
How to do this?
You can use the case expression for this...
select a.Br_Loan_No,
a.Br_LookupKey,
CASE WHEN s.Sample_Number IS NULL THEN 'N' ELSE 'Y' END AS [HasSample]
from dbo.tbl_Br a left outer join dbo.tbl_LoanSummary s
on s.Loan_no = a.Br_Loan_No order by a.Br_Loan_No
In Oracle, you could also use
select NVL(s.Sample_Number, 'N')
to return N in case of null value
(of course you still need something to have Y in case of not null.)
You'll want to use a CASE expression. It's like an embedded if-statement or switch-statement from traditional programming languages.
SELECT a.Br_Loan_No,
a.Br_LookupKey
CASE
WHEN s.Sample_Number IS NULL THEN 'N'
ELSE 'Y'
END AS sample_number_is_not_null
FROM dbo.tbl_Br a
LEFT JOIN dbo.tbl_LoanSummary s
ON s.Loan_no = a.Br_Loan_No
ORDER BY a.Br_Loan_no
Note that you are creating a computed column here, rather than selecting the raw value of an existing column. It's generally required that you give this column a name, thus the use of the AS sample_number_is_not_null.
There are two forms of the CASE expression. One lets you compare a column or value against several choices. It is like using an implicit equals:
CASE foo
WHEN 3 THEN 'foo is 3!'
WHEN 4 THEN 'foo is 4!'
ELSE 'foo is not 3 or 4'
END
The other form, in the example at the top, lets you use arbitrary expressions in each WHEN clause. It should be noted that each WHEN clause is evaluated in order and the first one to match is the one whose THEN is used as the result. If none of the WHENs match, then the result in the ELSE is used.

Oracle: How can I get a value 'TRUE' or 'FALSE' comparing two NUMBERS in a query?

I want to compare two numbers. Let's take i.e. 1 and 2.
I've tried to write the following query but it simply doesn't work as expected (Toad says: ORA-00923: FROM keyword not found where expected):
SELECT 1 > 2 from dual
The DECODE is something like a Switch case, so how can I get the result of an expression evalutation (i.e. a number comparison) putting it in the select list?
I have found a solution using a functions instead of an expression in the SELECT LIST: i.e.
select DECODE(SIGN(actual - target)
, -1, 'NO Bonus for you'
, 0,'Just made it'
, 1, 'Congrats, you are a winner')
from some_table
Is there a more elegant way?
Also how do I compare two dates?
There is no boolean types in sql (at least in oracle).
you can use case:
SELECT CASE when 1 > 2 THEN 1 ELSE 0 END FROM dual
But your solution (decode) is also good, read here
The SIGN() function is indeed probably the best way of classifying (in)equality that may be of interest to you if you want to test a > b, a = b and a < b, and it will accept date-date or numeric-numeric as an argument.
I'd use a Case statement by preference, rather than a decode.
Select
case sign(actual-target)
when -1 then ...
when 0 then ...
when 1 then ...
end
SELECT (CASE
WHEN (SIGN(actual - target) > 0 ) THEN
'NO Bonus for you'
ELSE
'Just made it' END)
FROM dual
you can compare two dates with sql
METHOD (1):
SELECT TO_DATE('01/01/2012') - TO_DATE('01/01/2012')
FROM DUAL--gives zero
METHOD (2):
SELECT CASE
when MONTHS_BETWEEN('01/01/2012','01/01/2010') > 0
THEN 'FIRST IS GREATER'
ELSE 'SECOND IS GREATER OR EQUAL' END
FROM dual
sorry i cant format the code the formatting toolbar disappeared !
do any one know why?

SQLServer - Select bool if column begins with a string

I would like to select a boolean of whether or not a column begins with a certain string.
SELECT (name LIKE 'foo%') AS isFoo FROM bar;
Is there a way to do this without using an inline CASE?
No
There is neither implicit boolean CAST in SQL Server nor a boolean type
SELECT CAST(CASE WHEN name LIKE 'foo%' THEN 1 ELSE 0 END AS bit) AS isFoo
FROM bar;
You might not even need the cast depending on your usage:
SELECT CAST(PATINDEX('foo%'), name) AS bit) FROM bar
This will return 1 if the col starts with the text otherwise 0. No CASE involved.
A UNION operation would let you skip a CASE statement by combining two result sets. In the first query you filter for all rows that match 'foo%' and in the second you match all rows that do not match 'foo%'
Something like:
SELECT 1 AS [YourBoolean], 'fool' WHERE 'fool' LIKE 'foo%'
UNION
SELECT 0, 'fuel' WHERE 'fuel' NOT LIKE 'foo%'
ORDER BY 1
(Hard-coded example w/o target table.)
Create a User Defined function that you can call inorder to check if the name contains foo.
Not to take away from what gbn suggested but I think this would be more efficient (but essentially the same thing)
SELECT CAST(CASE WHEN LEFT(name, 3)='foo' THEN 1 ELSE 0 END AS bit) AS isFoo
FROM bar;
SELECT
CASE WHEN name LIKE 'foo%'
THEN 1
ELSE 0
END as isFoo
FROM bar