SQL Server replace different characters in a column value - sql

I have a Barcode column with some data like below:
Z1B1S1A -- Zone 1 Bay 1 Shelf 1A
Z10B10S10B -- Zone 10 Bay 10 Shelf 10B
want to replace them with:
01-01-01A -- I think I can get by with 1-1-1A
10-10-10B
The zone, bay, shelf can go from 1 to 99.
The problem for me is the inconsistent with 1 or 2 digit, and the last char 'B' can be mistaken for the Bay number.
Thank you for any help.

2 solutions. First solution is from help & idea of Analyst & DeepShiKha
1. First solution
-- SUBSTRING ( expression ,start , length )
-- CHARINDEX ( expressionToFind , expressionToSearch [ , start_location ] )
select substring(Barcode,2,charindex('B',barcode)-2) AS Zoney,
substring(Barcode,charindex('B',Barcode)+1, charindex('S',Barcode)-charindex('B',Barcode)-1) AS Bay,
substring(Barcode,charindex('S',Barcode)+1,len(Barcode)) AS Shelf,
concat (
substring(Barcode,2,charindex('B',barcode)-2),'-',
substring(Barcode,charindex('B',Barcode)+1, charindex('S',Barcode)-charindex('B',Barcode)-1), '-',
substring(Barcode,charindex('S',Barcode)+1,len(Barcode))
) AS ZBS
from TB_BarcodeTag4
where Barcode LIKE 'Z%B%S%'
2. Second solution is from my own
UPDATE TB_BarcodeTag4
SET Barcode = STUFF(Barcode, LEN(Barcode),1, '&')
WHERE Barcode LIKE 'Z%B%S%' AND Barcode like '%B'
UPDATE TB_BarcodeTag4
SET Barcode = REPLACE(REPLACE(REPLACE(Barcode, 'Z', ''),'B','-'),'S','-')
WHERE Barcode LIKE 'Z%B%S%'
UPDATE TB_BarcodeTag4
SET Barcode = STUFF(Barcode, LEN(Barcode),1, 'B')
WHERE Barcode LIKE 'Z%B%S%' AND Barcode like '%&'

I am confident there is a much more beautiful way to do this but just wanted to give back to the forum that has given so much to me. Hope it helps.
This produces 4 columns.
1. Zone
2. Shelf
3. Bay
4. ZoneBayShelf (Last column is just a concatenation of previous three)
Used a combination of SUBSTR and LOCATE function to find the points at which to cut the BarCode.
CONCAT just to bring it altogether.
SELECT
SUBSTR(BARCODE,2,LOCATE("Z",BARCODE, 1)) AS ZONE,
SUBSTR(BARCODE,LOCATE("B",BARCODE, 1),
LOCATE("B",BARCODE, 1)-LOCATE("Z",BARCODE, 1)) AS BAY,
SUBSTR(BARCODE,LOCATE("S",BARCODE, 1),
LEN(BARCODE)) AS SHELF,
CONCAT( SUBSTR(BARCODE,2,LOCATE("Z",BARCODE, 1)),
"-", SUBSTR(BARCODE,LOCATE("B",BARCODE, 1),
LOCATE("B",BARCODE, 1)-LOCATE("Z",BARCODE, 1)).
"-", SUBSTR(BARCODE,LOCATE("S",BARCODE, 1),
LEN(BARCODE))
) AS ZoneShelfBay
FROM DATABASE

It might look a bit messy but i think following code should help you:
First select the parts of string we are interested in:
declare #T1 table (barcode varchar(max))
insert into #T1 values('Z1B1S1A'),('Z10B10S10B'),('Z99B99S99C')
select substring(barcode,2,charindex('B',barcode)-2),
substring(barcode,charindex('B',barcode)+1,
charindex('S',Barcode)-charindex('B',Barcode)-1),
substring(barcode,charindex('S',barcode)+1,len(barcode))
from #T1
Now we can format as required:
select right('00'+ substring(barcode,2,charindex('B',barcode)-2),2)
+'-'+
right('00' +
substring(barcode,charindex('B',barcode)+1,
charindex('S',Barcode)-charindex('B',Barcode)-1),2)
+'-'+
right('000' +
substring(barcode,charindex('S',barcode)+1,
len(barcode)),3)
from #T1

Related

SQL Server 2012 Removing part of string before and after specific, repeating character

Would you please assist with a perplexing string operator problem?
I need to parse a NVARCHAR(32), not null column called MachineName from table dbo.Log. The format is either:
AA-BBB-CCC-DDD
AA-BBB-CCCC-DDD
AA-BBB-CCC-DDDD
AA-BBB-CCCC-DDDD
I need the Result Set (as [Code]) to be either CCC or CCCC.
I consulted this article:
http://basitaalishan.com/2014/02/23/removing-part-of-string-before-and-after-specific-character-using-transact-sql-string-functions/
With this code:
SELECT DISTINCT [MachineName]
,REPLACE(SUBSTRING([MachineName], CHARINDEX('-', [MachineName],6), LEN([MachineName])), '-', '') AS [Code]
FROM [dbo].[Log]
My current Result Set is fine on the left, but the right needs refinement.
CCCDDD
CCCCDDDD
I would defintely appreciate your help! Thank you in advance
You can improvise on this: http://sqlfiddle.com/#!3/9eecb7d/588
with test as (
select cast('AA-BBB-CCC-DDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCCC-DDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCC-DDDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCCC-DDDD' as nvarchar(32)) as field1
)
select
substring(
substring(field1,8,32),
1,
charindex('-', substring(field1,8,32))-1
)
from test
Result:
CCC
CCCC
CCC
CCCC
With substring, we ignore the first 7 characters and start with 8th character. That'll give us CCCC-DDD and such. charindex will tell us the position of - in CCCC-DDD and such. We reapply substring on the substring; starting with first position and capturing all up until - was found.
In your case, you could do:
select distinct
substring(
substring(MachineName,8,32),
1,
charindex('-', substring(MachineName,8,32))-1
) as Code
from dbo.Log

Converting SQL varchar column values to $ format i.e. thousand separation

I have a varchar(256) column AttributeVal with all different type of text values.
I need to find out all $ values like $5000, $2000 etc & add thousand separator to them (only to these values, but not to the other text values present in that column).
Thus the updated values should look like $5,000 & $2,000.
If I am using following query, then it will end up converting all values & I need to concatenate $ manually :(
replace(convert(varchar, convert(Money, AttributeVal), 1), '.00', '')
NB : I know that these kind of formatting should be taken care in the application end, but our customer is adamant to have these customization to be stored in DB only.
I don't think you can do a replace statement based on a regular expression like that exactly. See this stackoverflow post asking the same question.
You may want to reinforce to your client that formatted data should not be stored in a database. That money value should probably be stored in a DECIMAL(13, 4) or something similar instead of a VARCHAR field mixed with other data as well.
Your question is a great example of why you don't want to do this. It makes simple things very difficult.
Try this
SELECT '$'+ PARSENAME( Convert(varchar,Convert(money,convert(Money, 100000)),1),2)
Output: $100,000
Hope this help!
try with this, this will take care of thousand separator :-)
'$'+convert(varchar(50), CAST(amount as money), -1) amount
Sample
;with cte (amount)
as
(
select 5000 union all
select 123254578.00 union all
select 99966.00 union all
select 0.00 union all
select 6275.00 union all
select 18964.00 union all
select 1383.36 union all
select 26622.36
)
select '$'+convert(varchar(50), CAST(amount as money), -1) amount
from cte
Here is my take on the problem:
select coalesce(cast(try_convert(money, value) as varchar(50)), value) converted
from (
values ('50')
, ('5000')
, ('3000.01')
, ('text')
) samples(value)
and the output:
converted
--------------------------------------------------
50.00
5000.00
3000.01
text
(4 row(s) affected)

Remove unwanted text from column values

I dont know how to do this. On my table I have descriptions mixed with description code. I need to remove the code description, just want the description. The description is just the first part without the acronym (capital letters at the end). I use SQL Server 2012
Example:
ColumnDescription
Chemistry Q
education E
psychology P
Sociology SOC
Documentation DOC
communication COM
Political Science CP
Pharmacy and Toxicology FT
Engineering Education (General) ING-G
If you are looking to simply strip the code that is at the end of each string, a way to do this is to identify the last space character in the string and then use SUBSTRING to extract everything before that character:
SELECT SUBSTRING(ColumnDescription, 0, LEN(ColumnDescription) - CHARINDEX(' ', REVERSE(ColumnDescription)) + 1) AS ColumnDescription
FROM Table
Note that I do not know what your table is called, so I called it Table.
This effectively reverses the column text (using REVERSE), finds the first occurrence of a space character (using CHARINDEX) and then subtracts this from the length of the text (using LEN).
Then a simple SUBSTRING is used to extract the left-most portion of the text, resulting in the output of:
ColumnDescription
-----------------
Chemistry
education
psychology
Sociology
Documentation
communication
Political Science
Pharmacy and Toxicology
Engineering Education (General)
Based on your sample data I would guess that your problem could be simplified to:
Split the string at the last space character in the string
In which case:
DECLARE #your_table table (
ColumnDescription varchar(100)
);
INSERT INTO #your_table (ColumnDescription)
VALUES ('Chemistry Q')
, ('education E')
, ('psychology P')
, ('Sociology SOC')
, ('Documentation DOC')
, ('communication COM')
, ('Political Science CP')
, ('Pharmacy and Toxicology FT')
, ('Engineering Education (General) ING-G');
SELECT *
, SubString(ColumnDescription, number_of_characters - last_space + 2, 100) As last_part
, SubString(ColumnDescription, 0, number_of_characters - last_space + 2) As first_part
FROM (
SELECT ColumnDescription
, Len(ColumnDescription) As number_of_characters
, Reverse(ColumnDescription) As reversed
, CharIndex(' ', Reverse(ColumnDescription)) As last_space
FROM #your_table
) As x;

Remove trailing zero from decimal number

I have a one database table field called Amount which type is decimal(18,6). so it is stored in database up to 6 decimal points like 9.786534 But while retrieving that field using select query i have to take care like following
Remove trialling zero e.g if number is 9.230000 then result is only 9.23
If decimal points are all zero then only remove only four trialling zero e.g If number is 9.000000 then result is 9.00
Result is up to 2 decimal point if there are trialling zero.
If we write simple query like
select TOP 1 Amount From EmployeeMaster
then it gives 9.230000
but my intension is to remove trailing zero..
Please help me..
It works for removing trailing zeros, but I am still not able to convert 9 to 9.00 in this method.
Declare #myvalue varchar(50),
#Price Varchar(50)
Set #Price = '9.230000'
set #Myvalue = reverse(substring(#Price,patindex('%.%',#Price)+1,len(#Price)))
SELECT
case
When patindex('%.%[1-9]%',#price) = 0 Then
substring(#price,1,patindex('%.%',#price)-1)
else
substring(#price,1,patindex('%.%',#price)-1) + '.' + Reverse(substring(#Myvalue,patindex('%[1-9]%',#Myvalue),len(#Myvalue)))
END
Coming from decimal(18,6) you could do...
select cast(Amount as decimal(18,2))
Most databases that support the CAST function will round the number while converting it. On SQLServer this is what I would do if I wanted rounding.
If what you actually want is a string with only two digits after the decimal then you could
select cast((Amount as decimal(18,2)) as nvarchar)
nvarchar is SQLServer's variable length unicode type. Databases do not agree much on string types. Your database may have a different one. The rest of that sql is ANSI standard. Not all dbs support that either but many do.
This should work
SELECT CAST(REPLACE(RTRIM(REPLACE(CAST(CAST(33.9082976 AS DECIMAL(38,8)) AS NVARCHAR(256)),'0',' ')),' ','0') AS FLOAT)
Does this work?
select TOP 1 ROUND(Amount, 2) From EmployeeMaster
TRY below mentioned code.
SELECT TOP 1 CONVERT(DECIMAL(10,2),Amount) From EmployeeMaster
Hope it will work as expected.
An alternative approach:
1) convert the decimal to a string;
2) split the string into 2 parts, separating the last 4 characters from the rest of the string;
3) remove trailing zeros from the last 4 characters;
4) concatenate the two parts back.
WITH data (V) AS (SELECT CAST(9.786534 AS decimal(18,6))
UNION ALL
SELECT CAST(9.78653 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7800 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7 AS decimal(18,6))
UNION ALL
SELECT CAST(9.00000 AS decimal(18,6))
)
, AsString (V) AS (SELECT CAST(V AS varchar) FROM data)
, Split (L, R) AS (SELECT LEFT(V, LEN(V) - 4), RIGHT(V, 4) FROM AsString)
, Adjusted AS (SELECT L,
REPLACE(RTRIM(REPLACE(R, '0', ' ')), ' ', '0') AS R
FROM Split)
SELECT Result = L + R FROM Adjusted
The output of the above script is:
Result
--------
9.786534
9.78653
9.78
9.70
9.00
I guess using patindex in your case:
CASE WHEN FLOOR(Amount) <> CEILING(Amount) THEN
LTRIM(SUBSTRING(STR(Amount, 18, 6), 1, LEN(STR(Amount, 18, 6)) - PATINDEX('%[^0]%', REVERSE(str(Amount, 18, 6))) + 1))
ELSE STR(Amount,18,2)
END
for a decimal(18,6) field this should work:
select trim(to_char(Amount, '999999999999999999.99')) from EmployeeMaster
(at least for Oracle, not sure about other types)

Uppercase first two characters in a column in a db table

I've got a column in a database table (SQL Server 2005) that contains data like this:
TQ7394
SZ910284
T r1534
su8472
I would like to update this column so that the first two characters are uppercase. I would also like to remove any spaces between the first two characters. So T q1234 would become TQ1234.
The solution should be able to cope with multiple spaces between the first two characters.
Is this possible in T-SQL? How about in ANSI-92? I'm always interested in seeing how this is done in other db's too, so feel free to post answers for PostgreSQL, MySQL, et al.
Here is a solution:
EDIT: Updated to support replacement of multiple spaces between the first and the second non-space characters
/* TEST TABLE */
DECLARE #T AS TABLE(code Varchar(20))
INSERT INTO #T SELECT 'ab1234x1' UNION SELECT ' ab1234x2'
UNION SELECT ' ab1234x3' UNION SELECT 'a b1234x4'
UNION SELECT 'a b1234x5' UNION SELECT 'a b1234x6'
UNION SELECT 'ab 1234x7' UNION SELECT 'ab 1234x8'
SELECT * FROM #T
/* INPUT
code
--------------------
ab1234x3
ab1234x2
a b1234x6
a b1234x5
a b1234x4
ab 1234x8
ab 1234x7
ab1234x1
*/
/* START PROCESSING SECTION */
DECLARE #s Varchar(20)
DECLARE #firstChar INT
DECLARE #secondChar INT
UPDATE #T SET
#firstChar = PATINDEX('%[^ ]%',code)
,#secondChar = #firstChar + PATINDEX('%[^ ]%', STUFF(code,1, #firstChar,'' ) )
,#s = STUFF(
code,
1,
#secondChar,
REPLACE(LEFT(code,
#secondChar
),' ','')
)
,#s = STUFF(
#s,
1,
2,
UPPER(LEFT(#s,2))
)
,code = #s
/* END PROCESSING SECTION */
SELECT * FROM #T
/* OUTPUT
code
--------------------
AB1234x3
AB1234x2
AB1234x6
AB1234x5
AB1234x4
AB 1234x8
AB 1234x7
AB1234x1
*/
UPDATE YourTable
SET YourColumn = UPPER(
SUBSTRING(
REPLACE(YourColumn, ' ', ''), 1, 2
)
)
+
SUBSTRING(YourColumn, 3, LEN(YourColumn))
UPPER isn't going to hurt any numbers, so if the examples you gave are completely representative, there's not really any harm in doing:
UPDATE tbl
SET col = REPLACE(UPPER(col), ' ', '')
The sample data only has spaces and lowercase letters at the start. If this holds true for the real data then simply:
UPPER(REPLACE(YourColumn, ' ', ''))
For a more specific answer I'd politely ask you to expand on your spec, otherwise I'd have to code around all the other possibilities (e.g. values of less than three characters) without knowing if I was overengineering my solution to handle data that wouldn't actually arise in reality :)
As ever, once you've fixed the data, put in a database constraint to ensure the bad data does not reoccur e.g.
ALTER TABLE YourTable ADD
CONSTRAINT YourColumn__char_pos_1_uppercase_letter
CHECK (ASCII(SUBSTRING(YourColumn, 1, 1)) BETWEEN ASCII('A') AND ASCII('Z'));
ALTER TABLE YourTable ADD
CONSTRAINT YourColumn__char_pos_2_uppercase_letter
CHECK (ASCII(SUBSTRING(YourColumn, 2, 1)) BETWEEN ASCII('A') AND ASCII('Z'));
#huo73: yours doesn't work for me on SQL Server 2008: I get 'TRr1534' instead of 'TR1534'.
update Table set Column = case when len(rtrim(substring (Column , 1 , 2))) < 2
then UPPER(substring (Column , 1 , 1) + substring (Column , 3 , 1)) + substring(Column , 4, len(Column)
else UPPER(substring (Column , 1 , 2)) + substring(Column , 3, len(Column) end
This works on the fact that if there is a space then the trim of that part of string would yield length less than 2 so we split the string in three and use upper on the 1st and 3rd char. In all other cases we can split the string in 2 parts and use upper to make the first two chars to upper case.
If you are doing an UPDATE, I would do it in 2 steps; first get rid of the space (RTRIM on a SUBSTRING), and second do the UPPER on the first 2 chars:
// uses a fixed column length - 20-odd in this case
UPDATE FOO
SET bar = RTRIM(SUBSTRING(bar, 1, 2)) + SUBSTRING(bar, 3, 20)
UPDATE FOO
SET bar = UPPER(SUBSTRING(bar, 1, 2)) + SUBSTRING(bar, 3, 20)
If you need it in a SELECT (i.e. inline), then I'd be tempted to write a scalar UDF