how to replace T-SQL CASE statement with efficient code - sql

how can i replace the following case statement with efficient code
SELECT
CASE WHEN LEN(Code.Description)>=30
THEN left(Code.Description, 30) + '...'
ELSE NominalCode.Description END AS ShortDescription
FROM Code
Because the data set it returns is going to be 30-50,000 records and according to lead dev this code is ridiculous. I need help

Presumably, you intend:
SELECT (CASE WHEN LEN(c.Description) > 30
THEN left(c.Description, 30) + '...'
ELSE c.Description
END) AS ShortDescription
FROM Code c;
That is, the Description column references all come from the same table. Your code is fine.
However, I would adjust the semantics so the resulting string always has the same length:
SELECT (CASE WHEN LEN(c.Description) > 30
THEN LEFT(c.Description, 27) + '...'
ELSE c.Description
END) AS ShortDescription
FROM Code c;

Other than adding a ShortDesc field to your Product Table, perhaps I would try the following
Concat(left(Code.Description,30),IIF(Len(Code.Description)>30,'...',''))
or even
left(Code.Description,30)+IIF(Len(Code.Description)>30,'...','')
EDIT
As you can see the same execution plan, however, the performance of my approach was 18% better. This test was done on an isolated machine with a sample size of 30,000 records.

Related

SQL CONCAT drops zeros from expression

I am trying different ways to put a 0 in front of month less than 10.
I tried the following expression but the 0 get dropped.
What am I doing wrong?
CASE
WHEN month([Transact_Date]) < 10
THEN CONCAT(str(0),STR(month([Transact_Date]),1))
ELSE month([Transact_Date])
END AS month_w_0
Thanks!
Tom
I think a left padding trick is what you want here. Assuming your database be SQL Server:
SELECT RIGHT('00' + STR(MONTH([Transact_Date])), 2) AS month_w_0
FROM yourTable;
You don't need a CASE expression for this. In more recent versions of SQL Server, the FORMAT function might also be able to handle this.
I have tested this and it returns the result you want:
select CASE WHEN mnt < 10 THEN
concat('0' , mnt)
ELSE mnt
END AS month_w_0
from ( select month([Transact_Date]) mnt
from test_t) A
I have realised what your problem is. YOu can do it this way too:
SELECT
CASE
WHEN month([Transact_Date]) < 10
THEN CONCAT(str(0),STR(month([Transact_Date]),1))
ELSE STR(month([Transact_Date]),1)
END AS month_w_0
from test_t
The problem is only the else part and I believe that is because case when clause returns only one type od data. In your then part you have tryed to retunr string and in the else part number.
Hope this helps...
Here is a demo

Updating Sum Case Statement Grouped By Id

I need to create update statement that will enable to sum converted values and write appropriate result based on case statement into database. This also must be grouped by id as we store answers that are then calculated and appropriate result must be saved to easy with analysing data.
I finally gave up after trying too many things and for today have enough. Could anyone with good heart and knowledge help please?
Below is the script I end up at the moment.
Update DB.sf_snew
Set answer =
(Case When
sum(cast(question1 as Int)) + sum(cast(question2 Int))
+ sum(cast(question3 as Int))
<= 20 Then 'reject' Else 'accept'
End
)
Group By Id
I cannot believe something that simple made my day really bad.
I appreciate any help from you.
Below is the example of data stored in a snwew table
Remove the sums and the group by:
Update DB.sf_snew
Set answer =
Case When
cast(question1 as Int) + cast(question2 Int)
+ cast(question3 as Int)
<= 20 Then 'reject' Else 'accept'
End
You don't need to use an aggregate, just do the following:
UPDATE DB.sf_snew
SET Answer = CASE WHEN CAST(Question1 AS INT) + CAST(Question2 AS INT) + CAST(Question3 AS INT) <= 20 THEN 'Reject' ELSE 'Accept' END
The UPDATE will automatically work row-by-row

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. :)

How to quickly compare many strings?

In SQL Server, I have a string column that contains numbers. Each entry I need is only one number so no parsing is needed. I need some way to find all rows that contain numbers from 400 to 450. Instead of doing:
...where my stringcolumn like '%400%' or stringcolumn like '%401%' or stringcolumn like '%402%' or ...
is there a better that can save on some typing?
There are also other values in these rows such as: '5335154', test4559#me.com', '555-555-5555'. Filtering those out will need to be taken into account.
...where stringcolumn like '4[0-4][0-9]' OR stringcolumn = '450'
You don't need the wildcard if you want to restrict to 3 digits.
Use regex to accomplish this.
...where stringcolumn like '4[0-4][0-9]' OR stringcolumn like '450'
one way
WHERE Column like '%4[0-4][09]%'
OR Column LIKE '%500%'
keep in mind that this will pick anything with the number in it, so 5000 will be returned as well
I would do the following:
select t.*
from (select t.*,
(case when charindex('4', col) > 0
then substrint(col, charindex('4', col), charindex('4', col) + 2)
end) as col4xx
from t
) t
where (case when isnumeric(col4xx) = 1
then (case when cast(col4xx as int) between 400 and 450 then 'true'
end)
end) = 'true'
I'm not a fan of having case statements in WHERE clauses. However, to ensure conversion to a number, this is needed (or the conversion could become a column in another subquery). Note that the following is not equivalent:
where col4xx between '400' and '450'
Since the string '44A' would match.

SQL:printing my own messages depending on query output

how can i print my own messages depending on the output of a SQL quesry.
Eg:
print "got it" when select * from emp wherempno=10; return atlest one record.
else " not presnet" when the above quesry returns 0 records
i just one one sql quesry and not a Pl/SQL code.I am using oracle 9 db.
You could try grabbing the total in a sub-query and then selectively returning the result in a case statement.
I don't have access to oracle at the moment, so the syntax may not be perfect, but something like below should work
select
case t.c
when 0 then 'not presnet'
else 'got it'
end as result
from
(select count(*) as c from emp wherempno=10) t
This works (tested on OracleXE):
SELECT CASE WHEN COUNT(1) = 0 THEN 'not present' ELSE 'got it' END
FROM emp
WHERE mpno = 10
Can you not use a ROWCOUNT to determine the number of rows affected, and then combine that with an IF statement to achieve what you are looking for?