Retun x character AFTER a string SQL Server - sql-server

I'm trying to return the following 4 characters after a string in a column 'E.Notes'
Example string 'Code: ABCD'
Target output 'ABCD'
I've tried to no avail ;-(
CASE WHEN CHARINDEX('<strong>Code:</strong> ', E.Notes) > 0 THEN
LEFT(E.Notes, CHARINDEX('<strong>Code:</strong> ', E.Notes) 4)
ELSE '' END

USE SUBSTRING() OR RIGHT() SHOULD BE OK.
CASE WHEN CHARINDEX('<strong>Code:</strong> ', E.Notes) > 0 THEN
SUBSTRING(E.Notes, CHARINDEX('<strong>Code:</strong> ', E.Notes) + LEN('<strong>Code:</strong> '), 255)
ELSE '' END
CASE WHEN CHARINDEX('<strong>Code:</strong> ', E.Notes) > 0 THEN
RIGHT(E.Notes,LEN( E.Notes) + 1 - LEN('<strong>Code:</strong>') - CHARINDEX('<strong>Code:</strong> ', E.Notes) )
ELSE '' END
AND YOU CAN USE RTRIM() OR LTRIM() TO GET RID OF SPACES.

Try this
DECLARE #Notes VARCHAR(200) = '<strong>Code:</strong> ABCDkkkk'
SELECT CASE
WHEN CHARINDEX('Code:', #Notes) > 0
THEN RIGHT(#Notes, LEN(#Notes) - CHARINDEX('Code:', #Notes) - 14)
ELSE ''
END
EDITED
By OP's demand to get only first 4 character from the string.
SELECT CASE
WHEN CHARINDEX('Code:', #Notes) > 0
THEN LEFT(RIGHT(#Notes, LEN(#Notes) - CHARINDEX('Code:', #Notes) - 14), 4)
ELSE ''
END

Related

How to insert a character into a string every 3 characters from the right

I have a string made up of numbers. The length of the string ranges anywhere from 1 character to 9 characters.
I want to insert a dash (-) every three characters from the right. This will only be relevant for strings with upwards of three characters.
This will just be a select statement, as I do not want to actually update the string itself.
For example,
8 should return 8
476 should return 476
4767 should return 4-767
45907392 should return 45-907-392
845907392 should return 845-907-392
This should work:
select
*,
replace(format(n,'#,#'),',','-')
from (values (8),(476),(4767),(45907392),(845907392)) x (n)
Change , to . if it's thousand separator in your system, or provide a culture as third parameter in FORMAT function so it always works the same.
Since SQL Server 2012 you can use the FORMAT function as described in the other answers. In case you want to format a string value like 'abcde' too you can use only string functions like this:
DECLARE #str VARCHAR(100) = '845907392';
-- 845-907-392
SELECT REVERSE(SUBSTRING(REVERSE(#str), 7, 3))
+ CASE WHEN LEN(#str)>6 THEN '-' ELSE '' END
+ REVERSE(SUBSTRING(REVERSE(#str), 4, 3))
+ CASE WHEN LEN(#str)>3 THEN '-' ELSE '' END
+ REVERSE(SUBSTRING(REVERSE(#str), 1, 3))
You can also create a function:
CREATE FUNCTION dbo.GetFormatTripleDash (#str varchar(255))
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #retStr VARCHAR(255) = REVERSE(SUBSTRING(REVERSE(#str), 7, 3))
+ CASE WHEN LEN(#str)>6 THEN '-' ELSE '' END
+ REVERSE(SUBSTRING(REVERSE(#str), 4, 3))
+ CASE WHEN LEN(#str)>3 THEN '-' ELSE '' END
+ REVERSE(SUBSTRING(REVERSE(#str), 1, 3))
RETURN(#retStr)
END
You can use this funtion like this:
-- 845-907-392
SELECT dbo.GetFormatTripleDash('845907392')
A more flexible solution using the function. Now you can use a much longer string value and you can define the part size separated by - character.
CREATE FUNCTION dbo.GetFormatDash (#str varchar(255), #partSize INT = 3)
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #startSize INT = 0;
DECLARE #retStr VARCHAR(255) = '';
WHILE #startSize < LEN(#str)
BEGIN
SET #retStr = REVERSE(SUBSTRING(REVERSE(#str), #startSize + 1, #partSize)) + CASE WHEN #startSize > 0 THEN '-' ELSE '' END + #retStr;
SET #startSize = #startSize + #partSize;
END
RETURN(#retStr)
END
You can use this improved function like this:
-- 12-345-678-901-234-567-890
SELECT dbo.GetFormatDash('12345678901234567890', DEFAULT)
SELECT dbo.GetFormatDash('12345678901234567890', 3)
-- 12345-67890-12345-67890
SELECT dbo.GetFormatDash('12345678901234567890', 5)
demo on dbfiddle.uk
Its a bit gross but it works! Try i
t and let me know if you agree
SELECT
CASE
WHEN LEN(yourColumn)>6 THEN format(CAST(YourColumn AS NUMERIC), '###-###-###')
WHEN LEN(YourColumn)>3 THEN format(CAST(YourColumn AS NUMERIC), '###-###')
ELSE YourColumn
END
Here is another way to do it, albeit more typing
SELECT
CASE
WHEN LEN(yourColumn)>6 THEN SUBSTRING(YourColumn, 1, 3) +'-'+ SUBSTRING(YourColumn, 4, 3)
WHEN LEN(YourColumn)>3 THEN REVERSE(SUBSTRING(REVERSE(YourColumn), 1, 3) +'-'+ SUBSTRING(REVERSE(YourColumn), 4, 3))
ELSE YourColumn
END
Try this. I'm sure it can also be extended to allow for any number of characters with a bit of effort
declare #input nvarchar(100) = '845907392'
declare #separator char(1) = '-'
--option1 - CTE
;with dash1 as (
select isnull(stuff(reverse(#input), 1+3, 0, #separator), reverse(#input)) as v
)
, dash2 as(
select isnull(stuff(v, 1+7, 0, #separator), v) as v from dash1
)
select reverse(v) from dash2
--option2 - Non CTE
select reverse(isnull(stuff(isnull(stuff(reverse(#input), 1+3, 0, #separator), reverse(#input)), 1+7, 0, #separator), isnull(stuff(reverse(#input), 1+3, 0, #separator), reverse(#input))))
Try this using format() function.
Select Replace(format(8, '#,##0'), ',', '-')
Select Replace(format(476, '#,##0'), ',', '-')
Select Replace(format(45907392, '#,##0'), ',', '-')
Select Replace(format(845907392, '#,##0'), ',', '-')
Live db<>fiddle demo.
A solution with a recursive CTE:
with cte as (
select col, len(col) - 3 pos from tablename
union all
select
cast(left(col, pos) + '-' + right(col, len(col) - pos) as varchar(100)),
pos - 3
from cte
where pos > 0
)
select col from cte
where pos <= 0
See the demo.
Results:
> | col |
> | :---------- |
> | 8 |
> | 476 |
> | 845-907-392 |
> | 45-907-392 |
> | 4-767 |

SQL case statement in a stored procedure

I have a SQL Server stored proc that contains a CASE statement. However, I need to append the values if multiple conditions are true.
So if a particular record has an Invalid Date And Mileage exceeded, I would like both values to be displayed in the NotArchiveableReason column.
How would I accomplish that?
, CASE
WHEN DateOfLoss < PolicyStartDate THEN 'Invalid Date'
WHEN MilesDriven > TotalMilesAllowed THEN 'Mileage exceeded'
WHEN LossStatusCode != 'R' THEN 'Status code is Review'
Else 'Unknown issue'
END
As NotArchiveableReason
If you want to concatenate results like Invalid Date, Mileage Exceeded then you may be looking for something like this.
ISNULL(
NULLIF(
STUFF(
CASE WHEN DateOfLoss < PolicyStartDate THEN ', Invalid Date' ELSE '' END
+ CASE WHEN MilesDriven > TotalMilesAllowed THEN ', Mileage exceeded' ELSE '' END
+ CASE WHEN LossStatusCode != 'R' THEN ', Status code is Review' ELSE '' END
, 1, 2, '')
,'')
, 'Unknown issue')
As NotArchiveableReason
The STUFF() removes the leading comma. The NULLIF() converts the empty string to null. The ISNULL() will populate "Unknown Issue" when none of the CASE statement conditions are met.
, CASE WHEN DateOfLoss < PolicyStartDate THEN 'Invalid Date ' ELSE '' END
+ CASE WHEN MilesDriven > TotalMilesAllowed THEN 'Mileage exceeded ' ELSE '' END
+ CASE WHEN LossStatusCode != 'R' THEN 'Status code is Review ' ELSE '' END
+ CASE WHEN NOT
( DateOfLoss < PolicyStartDate
AND MilesDriven > TotalMilesAllowed
AND LossStatusCode != 'R') THEN 'Unknown issue ' ELSE '' END
As NotArchiveableReason
, CASE WHEN DateOfLoss < PolicyStartDate THEN 'Invalid Date ' ELSE '' END
+ CASE WHEN MilesDriven > TotalMilesAllowed THEN 'Mileage exceeded ' ELSE '' END
+ CASE WHEN LossStatusCode != 'R' THEN 'Status code is Review ' ELSE '' END
CASE WHEN DateOfLoss >= PolicyStartDate OR MilesDriven <= TotalMilesAllowed
OR LossStatusCode = 'R'
THEN 'Unknown issue' END As NotArchiveableReason
How about expand the result set and let the application handle it
, CASE WHEN DateOfLoss < PolicyStartDate THEN 1 ELSE 0 END as InvalidDate
, CASE WHEN MilesDriven > TotalMilesAllowed THEN 1 ELSE 0 END as MileageExceeded
, CASE WHEN LossStatusCode != 'R' THEN 1 ELSE 0 END as StatusCodeIsReview
Then if all is zero it is an unknown issue?
EDIT
You can try this then. This is using an inner select to first find the problems and then combine it afterwards. In this sollution you can add many different checks in the inner select, and then combine them as you like in the outer.
select case when tmp.InvalidDate is null and tmp.MileageExceeded is null and tmp.StatusCodeIsReview is null then 'Unknown issue' else
stuff
(
(
COALESCE(', ' + NULLIF(tmp.InvalidDate, ''), '') +
COALESCE(', ' + NULLIF(tmp.MileageExceeded, ''), '') +
COALESCE(', ' + NULLIF(tmp.StatusCodeIsReview, ''), '')), 1, 2, '')
end as NotArchiveableReason from
(
select *
, CASE WHEN DateOfLoss < PolicyStartDate THEN 'Invalid Date' ELSE NULL END as InvalidDate
, CASE WHEN MilesDriven > TotalMilesAllowed THEN 'Mileage Exceeded' ELSE NULL END as MileageExceeded
, CASE WHEN LossStatusCode != 'R' THEN 'Status Code Is Review' ELSE NULL END as StatusCodeIsReview
from MyTest
) as tmp
Why dont you go with 3 case statements and then in a new query CONCAT them?
, CASE
WHEN DateOfLoss < PolicyStartDate THEN 'Invalid Date'
END as 1
WHEN MilesDriven > TotalMilesAllowed THEN 'Mileage exceeded'
END as 2
WHEN LossStatusCode != 'R' THEN 'Status code is Review'
END as 3
select 1+2+3 As NotArchiveableReason

Cannot set the Order By to my SQL Statement, need a workaround

I understand that I cannot have the SQL order by PaymentDate but my results come out not in Payment Date Order. Is there an easy way I can make sure the PERIOD column is in actual date order?
The SQL below works perfect its just if i add "--order by f.PaymentDate" I get 'Column "PaymentItem.PaymentDate" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.' So i'm trying to think how to get around this
select g.SiteDescription,
case a.Surname when '' then a.Company else a.Surname + ', ' + isnull(a.Forename,'') end as Landowner,
h.PaymentTypeDesc as [RentalElection],
d.RelevantProportion,#IN_showRelevantProportion as ShowRelevantProportion,
g.SiteId,a.LandownerId,e.PaymentTypeId,e.PaymentCategoryId,
case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end as Period,
sum(isnull(f.ActualPayment,0)) as Total
from
[Site] g,
Landowner a,
[Site] c,
SiteAgreement d,
Payment e,
PaymentItem f,
PaymentType h
where a.LandownerId = d.LandownerId
and g.SiteId = d.SiteId
and e.SiteAgreementId = d.SiteAgreementId
and f.PaymentId = e.PaymentId
and e.PaymentTypeId = h.PaymentTypeId
and f.paymentdate between #IN_daysFrom and #IN_daysTo
and isnull(f.ActualPayment,0) != 0
group by g.SiteDescription,
case a.Surname when '' then a.Company else a.Surname + ', ' + isnull(a.Forename,'') end,
h.PaymentTypeDesc,
d.RelevantProportion,
g.SiteId,a.LandownerId,e.PaymentTypeId,e.PaymentCategoryId,
case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end
--order by f.PaymentDate
Order by the entire expression that uses your Payment Date column:
ORDER BY case #IN_OutputFormat
when 'Monthly' then
convert(char(3), f.PaymentDate, 0) + '-' + ltrim(Year(f.PaymentDate))
when 'Annually' then
ltrim(Year(f.PaymentDate))
else
ltrim(Year(f.PaymentDate)) + ' Qtr ' + ltrim(datepart(quarter,f.PaymentDate))
end
I got this going by just ordering at a string in format YYYY-MM. The MM needed left padded 0 of course:
CONVERT(CHAR(4), f.PaymentDate, 120) + ' ' + right('0'+ rtrim(ltrim(datepart(mm,f.PaymentDate))), 2)

find from a column having csv values in sql

I have a column (data) in database having values like
id name data
1 jatin 1,11,15
2 harsh 3,5,11
what can I do if I want to get the names of persons having 11 in data column??
thanks
On MS SQL Server you cannot use the FIND_IN_SET function, and would have to do something like this instead:
SELECT * FROM MyTable
WHERE ',' + Data + ',' LIKE '%,11,%'
I've added the commas in front and in the end of the Data column, to ensure that the LIKE operator works, even if "11" is at the beginning or the end of the string.
You can use this function:
CREATE FUNCTION CSV2Table (#var VARCHAR(max))
RETURNS TABLE
AS
RETURN (
-- Recursive CTE
WITH CSV(pop, variable) AS (
-- Base case
SELECT CASE
WHEN charindex(',', #var) > 0
THEN substring(#var, 1, charindex(',', #var) - 1)
ELSE #var
END,
CASE
WHEN charindex(',', #var) > 0
THEN substring(#var, charindex(',', #var) + 1, len(#var) - charindex(',', #var) + 1)
ELSE ''
END
UNION ALL
-- Recursive
SELECT CASE
WHEN charindex(',', CSV.variable) > 0
THEN substring(CSV.variable, 1, charindex(',', CSV.variable) - 1)
ELSE CSV.variable
END,
CASE
WHEN charindex(',', CSV.variable) > 0
THEN substring(CSV.variable, charindex(',', CSV.variable) + 1, len(CSV.variable) - charindex(',', CSV.variable) + 1)
ELSE ''
END
FROM CSV
WHERE len(CSV.variable) > 0
)
SELECT pop
FROM CSV
)
GO
and do something like:
SELECT * FROM <TABLE> WHERE EXISTS(SELECT TOP 1 1 FROM dbo.CSV2Table(data) WHERE POP = '11')

Remove Leading Commas via Coalasce and NULLIF?

UPDATE PropertyInformationDump
SET RegistryAdd = COALESCE(NULLIF(b.OCAREOF, ''), b.OCAREOF + ', ','') +
COALESCE(NULLIF(b.O1STADD, ''), b.O1STADD + ', ','') +
COALESCE(NULLIF(b.O2NDADD, '') + b.O2NDADD + ', ','') +
COALESCE(b.OSTNAME + ', ','') + COALESCE(b.OCITYST + ' ','') +
COALESCE(NULLIF(b.OZIP, ''), b.OZIP,'')
FROM dbo.vw_BRT b
WHERE BRTNumber = b.PARCEL
GO
Looking to remove the commas that are in the front of these combined strings. Here is an example of what is happening:
, , 1350 SUSQUEHANNA AVE, PHILADELPHIA PA 19125
MICHAEL J CARLONE, 10050 ROOSEVELT BLVD, PHILADELPHIA PA 191163924
Need it to always look like:
1350 SUSQUEHANNA AVE, PHILADELPHIA PA 19125
or just how the one with the OCAREOF filled:
MICHAEL J CARLONE, 10050 ROOSEVELT BLVD, PHILADELPHIA PA 191163924
I need to get rid of those commas if the field is empty or null. Apparently I am doing this incorrectly!
using SQL Server 2005 the following should work
UPDATE PropertyInformationDump
SET RegistryAdd =
CASE WHEN Len(b.OCAREOF) > 0 THEN b.OCAREOF + ',' ELSE '' END +
CASE WHEN Len(b.O1STADD) > 0 THEN b.O1STADD + ',' ELSE '' END +
CASE WHEN Len(b.O2NDADD) > 0 THEN b.O2NDADD + ',' ELSE '' END +
CASE WHEN Len(b.OSTNAME ) > 0 THEN b.OSTNAME + ',' ELSE '' END +
CASE WHEN Len(b.OCITYST) > 0 THEN b.OCITYST+ ',' ELSE '' END +
CASE WHEN Len(b.OZIP) > 0 THEN b.OZIP+ ',' ELSE '' END
FROM dbo.vw_BRT b
WHERE BRTNumber = b.PARCEL
If the fields are either empty of have data then you can ignore using isNull()
Use this:
COALESCE(NULLIF(b.OCAREOF + ', ', ''),'')
UPDATE
If your fields are not nullable use this:
CASE WHEN LEN(b.OCAREOF) = 0 THEN '' ELSE b.OCAREOF + ', ' END +
....

Resources