How to perform Case statement inside a select statement? - sql

I wanted to put 'No record' on the column instead of NULL if the datediff function returns a null value.
SELECT concat(e.firstname ,e.lastname) as Fullname,c.shiftcode as Shift, cast(c.datecheckinout as date) Date,datename(month, c.datecheckinout) as RecordMonth,c.timein , c.timeout,
CAST(
CASE
WHEN (datediff(HOUR,c.timein,c.timeout) IS NULL)
THEN 'No record'
END
), FROM tblCheckInOutDetail c RIGHT JOIN tblEmployee e on e.IdEmployee = c.IdEmployee WHERE e.IdEmployee = 55
So far this code only throws Incorrect syntax near 'CAST', expected 'AS'. but I don't know what data type should I put in the CAST parameter , since if there's a record it will show the datetime .

You need to convert the number value to a string. For this, you can use coalesce():
SELECT concat(e.firstname ,e.lastname) as Fullname,c.shiftcode as Shift, cast(c.datecheckinout as date) Date,datename(month, c.datecheckinout) as RecordMonth,c.timein , c.timeout,
COALESCE(CAST(datediff(HOUR, c.timein, c.timeout) AS VARCHAR(255)), 'No record')
FROM tblEmployee e LEFT JOIN
tblCheckInOutDetail c
ON e.IdEmployee = c.IdEmployee
WHERE e.IdEmployee = 55;
Note: I switched the RIGHT JOIN to a LEFT JOIN. They are equivalent logically. But most people find it much easier to follow the logic of the LEFT JOIN, because the table that defines the rows is the first table being read in the FROM clause.

Strictly answering question (though I don't understand why you need a CASE expression if you have working versions of the query), you can easily translate this to a CASE expression:
ISNULL(CAST(datediff(HOUR,c.timein,c.timeout) as varchar),'No Record')
ISNULL really is just nice, convenient shorthand for CASE WHEN a IS NOT NULL THEN a ELSE b END, so:
CASE WHEN DATEDIFF(HOUR, c.timein, c.timeout) IS NOT NULL
THEN CAST(datediff(HOUR,c.timein,c.timeout) as varchar(11))
ELSE 'No Record' END
As you can see, a downside is that if you really really really want a CASE expression, you have to repeat at least the DATEDIFF to cover both the case where the outer row doesn't exist and the case where the outer row exists but one of the values is NULL.
Also note that you should always specify a length for variable types like varchar, even in cases where you think you're safe with the default.

I don't know if this is the correct option or usage.
but this works for me :
ISNULL(CAST(datediff(HOUR,c.timein,c.timeout) as varchar),'No Record')
But can you guys show me how to do this using case expression?

Related

CASE expression with NULL value

I'm struggling to understand how to check for a null value in a progress case expression. I want to see if a column exists and use that, if not use the fallback column. For example, William in first name would be over written by Bill in fn.special-char.
I've got the following query:
SELECT
"PUB"."NAME"."LAST-NAME" as LastName,
CASE fn."SPECIAL-CHAR"
WHEN is null THEN "PUB"."NAME"."FIRST-NAME"
ELSE fn."SPECIAL-CHAR"
END as FirstName
FROM "PUB"."NAME"
LEFT OUTER JOIN "PUB"."DAT-DATA" fn on "PUB"."NAME"."NAME-ID" = fn."DAT-SRC-ID" and 11 = fn."FLD-FIELD-ID"
When I run the query I get:
ORBC Progress OpenEdge Wire Protocol driver][OPENEDGE]Syntax error SQL statement at or about "is null then "PUB"."NAME"."FIRST-" (10713)
If I do a select * I see everything. It just doesn't like the null part. I can also change the when is null to when 'bob' and it works.
Is there something different I need to do to use a null value in a progress db query?
The shorthand variation of the case statement (case expression when value then result ...) is a shorthand for a series of equality conditions between the expression and the given values. null, however, is not a value - it's the lack thereof, and must be evaluated explicitly with the is operator, as you tried to do. In order to do this properly, however, you need to use a slightly longer variation of the case syntax - case when condition then result ...:
SELECT
"PUB"."NAME"."LAST-NAME" as LastName,
CASE WHEN fn."SPECIAL-CHAR" IS NULL THEN "PUB"."NAME"."FIRST-NAME"
ELSE fn."SPECIAL-CHAR"
END as FirstName
FROM "PUB"."NAME"
LEFT OUTER JOIN "PUB"."DAT-DATA" fn on "PUB"."NAME"."NAME-ID" = fn."DAT-SRC-ID" and 11 = fn."FLD-FIELD-ID"
Instead of CASE you can use IFNULL function in Progress 4GL.
SELECT
"PUB"."NAME"."LAST-NAME" as LastName,
IFNULL(fn."SPECIAL-CHAR", "PUB"."NAME"."FIRST-NAME") as FirstName
FROM "PUB"."NAME"
LEFT OUTER JOIN "PUB"."DAT-DATA" fn on "PUB"."NAME"."NAME-ID" = fn."DAT-SRC-ID" and 11 = fn."FLD-FIELD-ID"

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.

SELECT one of two Ints and apply conditional formatting

I have a table [Case] which amongst other fields has two ints, one called [CaseNo] and the other [QueryNo]. Only one of these will exist at any one time, the other will return Null.
I want a SELECT statement that will return [CaseNo] if it exists, and if it doesn't it should return the [QueryNo] proceeded by a 'Q' to denote it is a [QueryNo].
I tried the following statement -
SELECT CONVERT(VarChar(50), (ISNULL(CaseNo, 'Q' + QueryNo)))
FROM [Case]
But it does not like my Conversion.
Could someone please help me get the right Statement to achieve my objective.
Using a CASE statement:
Select Case when caseNo is null then 'Q'+ Convert(varchar(10),queryNo)
else Convert(varchar(10),caseNo) end as yourNo
from [Case]
Or if you like using isnull/coalesce, you could do:
Select isnull(Convert(varchar(10), caseNo),'Q' + Convert(varchar(10), queryNo)) yourNo
from [Case]

SQL Doesnt Want to match strings with spaces for some reason

I have this SQL Query that is not comparing properly so I commented it out the WHERE clause. When returning the AF.ActivityNote it always has 2 spaces after it no matter if I do RTRIM on it or not. I think those spaces are the issue that wont let the commented WHERE clause to properly match the string against userfield33.
SELECT CAST(UF.UserField33 AS NVARCHAR) , RTRIM(CAST(AF.ActivityNote AS NVARCHAR))
FROM [BCMTEST01].[dbo].[ActivityContacts] as AC INNER JOIN [BCMTEST01].[dbo].[ActivityFullView] as AF
ON AC.ActivityID = AF.ActivityID INNER JOIN [BCMTEST01].[dbo].[OpportunityExportView] as OP
ON AC.ContactID = OP.ContactServiceID INNER JOIN [BCMTEST01].[dbo].[UserFields] as UF
ON OP.ContactServiceID = UF.ContactServiceID
WHERE ContactID = 8376
--WHERE RTRIM(CAST(UF.UserField33 AS NVARCHAR) = RTRIM(CAST(AF.ActivityNote AS NVARCHAR))
ORDER BY ContactID ASC
First, you should always include the length when converting to nvarchar, varchar, char, and nchar. So use something like:
cast(uf.userfield33 as nvarchar(255)) -- or whatever length you like, so long as you have something
The last two characters are not spaces. Do something like:
select ascii(right( AF.ActivityNote, 1))
To see what the character value is. You can then use replace to get rid of it. Or, you can just chop off the last two characters (if that works for your application).
By the way, I am assuming you are using SQL Server based on the syntax of the query.
Here is an alternative where clause:
where (case when right(AF.ActivityNote, 2) = char(10)+CHar(13)
then LEFT(AF.ActivityNote, LEN(AF.ActivityNote) - 2)
else AF.ActivityNote
end) = CAST(UF.UserField33 AS NVARCHAR(255)
I'm not a big fan of case statements in where clauses. I would actually put the logic in a subquery. Also, I might have the order of the 10/13 backwards.

How to replace null into 0 in a complex query

I would like to replace the total value to 0 when it is null
Here is the query:
SELECT DISTINCT(location), (
SELECT Count(a.location) as total
FROM table_fo a
LEFT JOIN table_info b ON a.TRADEID = b.TRADEID AND a.asofdate = b.asofdate
WHERE (b.TERMSTATUS <> 'TRAN' OR b.TERMSTATUS is NULL) AND b.asofdate = '20110105' AND a.location = pfo.location
GROUP BY a.LOCATION
) AS total
FROM table_fo pfo
WHERE asofdate = '20110105';
You can use the ISNULL function.
Here is how you will use the function (for SQL Server).
ISNULL(columnName, 0)
I would like to replace the total
value to 0 when it is null
This is an impossible situation because:
The COUNT function always returns an integer. The result cannot be NULL!
As for coalescing an expression to a certain default in case it is NULL there are functions that do this in all major databases (ex.: COALESCE, NVL, ISNULL, IFNULL). The typical use is
FUNCTION_NAME(ExpressionThatMayBeNULL, DefaultWhenNull)
For specifics you should consult you database manufacturers documentation (you can find it online).
COALESCE will do this in PL/SQL (Oracle) and T-SQL (SQL Server)
Syntax is COALESCE(field1, field2[, fieldN]) - it will select the first column from the left to have a non-null value.
Modifying the query you had:
SELECT DISTINCT(location), COALESCE((
SELECT Count(a.location) as total
FROM table_fo a
LEFT JOIN table_info b ON a.TRADEID = b.TRADEID AND a.asofdate = b.asofdate
WHERE (b.TERMSTATUS <> 'TRAN' OR b.TERMSTATUS is NULL) AND b.asofdate = '20110105' AND a.location = pfo.location
GROUP BY a.LOCATION
),0) AS total
FROM table_fo pfo
WHERE asofdate = '20110105';
As dparker said, ISNULL(...) will work for some types of sql, though the name of the function can vary among database providers.
The function in IBM DB2 is called COALESCE(...), and in Oracle SQL it is NVL(...) for example.
This may be usefull
http://www.w3schools.com/sql/sql_isnull.asp
If you are using SQL server, the following are the 3 ways that can be used to replace a null with any user defined substitute value.
1. ISNULL
2. COALESCE
3. CASE
This question is also asked in one of the interviews I attended. Here is the link for an article with examples. By the way, there's also a video on the same in this article.
Different ways to replace NULLS in SQL Server
What DB system are you using?
SQL-Server, MySQL: IFNULL(value, 0)
Oracle: NVL(value, 0)
PostgreSQL: COALESCE(value, 0)