Unexpected execution in an update query in SQL - sql

I am getting an 'Unexpected' result with an update query in SQL Server 2012.
This is what I am trying to do.
From a column (IDENTIFIER) composed by an ID ','name (e.g. 258967,Sarah Jones), I have to fill other two columns: ID and SELLER_NAME.
The original column has some values with a blank at the end and the rest with out it:
'258967,Sarah Jones'
'98745,Richard James '
This is the update query that I am executing:
UPDATE SELLER
SET
IDENTIFIER = LTRIM(RTRIM(IDENTIFIER)),
ID = Left(IDENTIFIER , charindex(',', IDENTIFIER )-1),
SELLER_NAME = UPPER(RIGHT((IDENTIFIER ),LEN(IDENTIFIER )-CHARINDEX(',',IDENTIFIER )));
But I am having a wrong result at the end
258967,Sarah Jones 258967 SARAH JONES
98745,Richard James 98745 ICHARD JAMES
The same happens with all the names that has the blank at the end. At this point I wonder, if I have specified that I want to eliminate all the blanks at the begining and at the end of the value of IDENTIFIER as a first action, why the system updates the ID and SELLER_NAMES and then does this action?.
Just to specify: The IDENTIFIER column is part of the seller table which is updating from another person that imports the data from an Excel file. I receive this values and I have to normalize the information. I only can read the SELLER table, take this into account before answer

Try this, because you have space in right side of name, so it will just truncate one char from name. So just need to RTRIM(IDENTIFIER) and thats it.
SELLER_NAME = UPPER(RIGHT((RTRIM(IDENTIFIER)),LEN(IDENTIFIER )-CHARINDEX(',',IDENTIFIER)));

The design of your tables violates 1NF and is nothing but painful. Instead of doing all this crazy string manipulation you could leverage PARSENAME here quite easily.
with Something(SomeValue) as
(
select '258967,Sarah Jones' union all
select '98745,Richard James '
)
select *
, ltrim(rtrim(PARSENAME(replace(SomeValue, ',', '.'), 2)))
, ltrim(rtrim(PARSENAME(replace(SomeValue, ',', '.'), 1)))
from Something

Instead of using Right(), use SubString().
Here's an example. I've tried to show each step individually to illustrate
; WITH x (identifier) AS (
SELECT '258967,Sarah Jones'
UNION ALL
SELECT '98745,Richar James '
)
SELECT identifier
, CharIndex(',', identifier) As comma
, SubString(identifier, CharIndex(',', identifier) + 1, 1000) As name_only
, LTrim(RTrim(SubString(identifier, CharIndex(',', identifier) + 1, 1000))) As trimmed_name_only
FROM x
Note that the 1000 used should be the maximum length of the column definition or higher e.g. if your IDENTIFIER column is a varchar(2000) then use 2,000 instead.

try trim the IDENTIFIER first like this
SALLER_NAME = UPPER(RIGHT((RTRIM(IDENTIFIER),LEN(IDENTIFIER )-CHARINDEX(',',IDENTIFIER )));

Related

How to fetch only a part of string

I have a column which has inconsistent data. The column named ID and it can have values such as
0897546321
ABC,0876455321
ABC,XYZ,0873647773
ABC,
99756
test only
The SQL query should fetch only Ids which are of 10 digit in length, should begin with a 08 , should be not null and should not contain all characters. And for those values, which have both digits and characters such as ABC,XYZ,0873647773, it should only fetch the 0873647773 . In these kind of values, nothing is fixed, in place of ABC, XYZ , it can be anything and can be of any length.
The column Id is of varchar type.
My try: I tried the following query
select id
from table
where id is not null
and id not like '%[^0-9]%'
and id like '[08]%[0-9]'
and len(id)=10
I am still not sure how should I deal with values like ABC,XYZ,0873647773
P.S - I have no control over the database. I can't change its values.
SQL Server generally has poor support regular expressions, but in this case a judicious use of PATINDEX is viable:
SELECT SUBSTRING(id, PATINDEX('%,08[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],%', ',' + id + ','), 10) AS number
FROM yourTable
WHERE ',' + id + ',' LIKE '%,08[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],%';
Demo
If you normalise your data, and split the delimited data into parts, you can achieve this some what more easily:
SELECT SS.value
FROM dbo.YourTable YT
CROSS APPLY STRING_SPLIT(YT.YourColumn,',') SS
WHERE LEN(SS.value) = 10
AND SS.value NOT LIKE '%[^0-9]%';
If you're on an older version of SQL Server, you'll have to use an alternative String Splitter method (such as a XML splitter or user defined inline table-value function); there are plenty of examples on these already on Stack Overflow.
db<>fiddle

get sub string in between mix symbols

I want to get sub string my output should look like gmail,outlook,Skype.
my string values are
'abc#gmail.com'
'cde.nitish#yahoo.com'
'xyz.vijay#sarvang.com.com'
somthing like this as you can see its having variable length with mix symbol '.' and '#'
string values store in table form as a column name Mail_ID and Table name is tbl_Data
i am using sql server 2012
i use chart index for getting sub string
select SUBSTRING(Mail_ID, CHARINDEX('#',MAil_ID)+1, (CHARINDEX('.',MAil_ID) - (CHARINDEX('#', Mail_ID)+1)))
from tbl_data
And i want my output like:
'gmail'
'yahoo'
'sarvang'
Please help me i am newbies in sql server
This is my solution. I first get the position of the '#', and then get the position of the '.' in the string prior to it (the '#'). Then I can use those results to get the appropriate substring:
SELECT V.YourString,
SUBSTRING(V.YourString,D.I,A.I - D.I) AS StringPart
FROM (VALUES('abc#gmail.com'),
('cde.nitish#yahoo.com'),
('xyz.vijay#sarvang.com.com'))V(YourString)
CROSS APPLY(VALUES(CHARINDEX('#',V.YourString)))A(I) --Get position of # to not repeat logic
CROSS APPLY(VALUES(CHARINDEX('.',LEFT(V.YourString,A.I))+1))D(I) --Get position of . to not repeat logic
Note for value of 'abc.def.steve#... it would return 'def.steve'; however, we don't have such an example so I don't know what the correct return value would be.
I'm posting this as a new answer, a the OP moved the goal posts from the original answer. My initial answer was based on their original question, not their "new" one, and it seems silly to remove an answer that was correct at the time:
SELECT V.YourString,
SUBSTRING(V.YourString,A.I, D.I - A.I) AS StringPart
FROM (VALUES('abc#gmail.com'),
('cde.nitish#yahoo.com'),
('xyz.vijay#sarvang.com.com'))V(YourString)
CROSS APPLY(VALUES(CHARINDEX('#',V.YourString)+1))A(I)
CROSS APPLY(VALUES(CHARINDEX('.',V.YourString,A.I)))D(I);
This answers the original version of the question.
This may be simplest with a case expression to detect if there is a period before the '#':
select (case when email like '%.%#%'
then stuff(left(email, charindex('#', email) - 1), 1, charindex('.', email), '')
else left(email, charindex('#', email) - 1)
end)
from (values ('abc#gmail.com'), ('cde.nitish#yahoo.com'), ('xyz.vijay#sarvang.com.com')) v(email)
I create a temp table with your data and write below query its worked
CREATE TABLE #T
(
DATA NVARCHAR(50)
)
INSERT INTO #T
VALUES('abc#gmail.com'),
('cde.nitish#yahoo.com'),
('xyz.vijay#sarvang.com.com')
SELECT *,LEFT(RIGHT(DATA,LEN(DATA)-CHARINDEX('#',DATA,1)),CHARINDEX('.',RIGHT(DATA,LEN(DATA)-CHARINDEX('#',DATA,1)),1)-1)
FROM #t
AND its a output of my T-SQL
abc#gmail.com gmail
cde.nitish#yahoo.com yahoo
xyz.vijay#sarvang.com.com sarvang

How to find repeating numbers in a column in SQL server . Eg 11111, 33333333, 5555555555,7777777 etc

I need to identify repeated numbers( Eg: 1111, 33333333, 5555555555,777777777 etc.) in a column.
How can I do this in sql server without having to hard code every scenario. The max length is 10 of the column. Any help is appreciated.
This will check if the column has all the same value in it.
SELECT *
FROM tablename
WHERE columnname = REPLICATE(LEFT(columnname,1),LEN(columnname))
As Nicholas Cary notes, if the column is numbers you'd need to cast as varchar first:
SELECT *
FROM tablename
WHERE CAST(columnname AS VARCHAR(10)) = REPLICATE(LEFT(CAST(columnname AS VARCHAR(10)),1),LEN(CAST(columnname AS VARCHAR(10))))
Riffing on #Dave.Gugg's excellent answer, here's another way, using patindex() to look for a character different than the first.
select *
from some_table t
where 0 = patindex( '[^' + left(t.some_column,1) + ']' , t.some_column )
Again, this only works for string types (char,varchar, etc.). Numeric types such as int will need to be converted first.

Sorting (or usage of ORDER BY clause) in T-SQL / SQL SERVER without considering some words

i'm wondering whether it is possible to use ORDER BY clause (or any other clause(s)) to do sorting without considering some words.
For ex, article 'the':
Bank of Switzerland
Bank of America
The Bank of England
should be sorted into:
Bank of America
The Bank of England
Bank of Switzerland
and NOT
Bank of America
Bank of Switzerland
The Bank of England
select * from #test
order by
case when test like 'The %' then substring(test, 5, 8000) else test end
If you have a limited number of words that you wish to eliminate, then you might be able to remove them by judicious use of REPLACE, e.g.
ORDER BY REPLACE(REPLACE(' ' + Column + ' ',' the ',' '),' and ',' ')
However, as the number of words add up, you'll have more and more nested REPLACE calls. In addition, this ORDER BY will be unable to benefit from any indexes, and doesn't cope with punctuation marks.
If this sort is frequent and the queries would otherwise be able to benefit from an index, you might consider making the above a computed column, and creating an index over it (You would then order by the computed column).
You need to encode a method of turning one string into another and then ordering by that.
For example, if the method is just to strip away starting occurances of 'The '...
ORDER BY
CASE WHEN LEFT(yourField, 4) = 'The ' THEN RIGHT(yourField, LEN(yourField)-4) ELSE yourField END
Or, if you want to ignore all occurrences of 'the', where ever it occurs, just use REPLACE...
ORDER BY
REPLACE(yourField, 'The', '')
You may end up with a fairly complex transposition, in which case you can do things like this...
SELECT
*
FROM
(
SELECT
<complex transposition> AS new_name,
*
FROM
whatever
)
AS data
ORDER BY
new_name
No, not really because the is arbitrary in this case. The closest you can do is modify the field value, such as below:
SELECT field1
FROM table
ORDER BY REPLACE(field1, 'The ', '')
The problem is that to replace two words, you have to next REPLACE statements, which becomes a huge issue if you have more than about five words:
SELECT field1
FROM table
ORDER BY REPLACE(REPLACE(field1, 'of ', ''), 'The ', '')
Update: You don't really need to check if the or of appears at the beginning of the field because you are only wanting to sort by important words anyway. For example, Bank of America should appear before Bank England (the of shouldn't make it selected after).
My Solution a little bit shorter
DECLARE #Temp TABLE ( Name varchar(100) );
INSERT INTO #Temp (Name)
SELECT 'Bank of Switzerland'
UNION ALL
SELECT 'Bank of America'
UNION ALL
SELECT 'The Bank of England'
SELECT * FROM #Temp
ORDER BY LTRIM(REPLACE(Name, 'The ', ''))

SQL strip text and convert to integer

In my database (SQL 2005) I have a field which holds a comment but in the comment I have an id and I would like to strip out just the id, and IF possible convert it to an int:
activation successful of id 1010101
The line above is the exact structure of the data in the db field.
And no I don't want to do this in the code of the application, I actually don't want to touch it, just in case you were wondering ;-)
This should do the trick:
SELECT SUBSTRING(column, PATINDEX('%[0-9]%', column), 999)
FROM table
Based on your sample data, this that there is only one occurence of an integer in the string and that it is at the end.
I don't have a means to test it at the moment, but:
select convert(int, substring(fieldName, len('activation successful of id '), len(fieldName) - len('activation successful of id '))) from tableName
Would you be open to writing a bit of code? One option, create a CLR User Defined function, then use Regex. You can find more details here. This will handle complex strings.
If your above line is always formatted as 'activation successful of id #######', with your number at the end of the field, then:
declare #myColumn varchar(100)
set #myColumn = 'activation successful of id 1010102'
SELECT
#myColumn as [OriginalColumn]
, CONVERT(int, REVERSE(LEFT(REVERSE(#myColumn), CHARINDEX(' ', REVERSE(#myColumn))))) as [DesiredColumn]
Will give you:
OriginalColumn DesiredColumn
---------------------------------------- -------------
activation successful of id 1010102 1010102
(1 row(s) affected)
select cast(right(column_name,charindex(' ',reverse(column_name))) as int)
CAST(REVERSE(LEFT(REVERSE(#Test),CHARINDEX(' ',REVERSE(#Test))-1)) AS INTEGER)
-- Test table, you will probably use some query
DECLARE #testTable TABLE(comment VARCHAR(255))
INSERT INTO #testTable(comment)
VALUES ('activation successful of id 1010101')
-- Use Charindex to find "id " then isolate the numeric part
-- Finally check to make sure the number is numeric before converting
SELECT CASE WHEN ISNUMERIC(JUSTNUMBER)=1 THEN CAST(JUSTNUMBER AS INTEGER) ELSE -1 END
FROM (
select right(comment, len(comment) - charindex('id ', comment)-2) as justnumber
from #testtable) TT
I would also add that this approach is more set based and hence more efficient for a bunch of data values. But it is super easy to do it just for one value as a variable. Instead of using the column comment you can use a variable like #chvComment.
If the comment string is EXACTLY like that you can use replace.
select replace(comment_col, 'activation successful of id ', '') as id from ....
It almost certainly won't be though - what about unsuccessful Activations?
You might end up with nested replace statements
select replace(replace(comment_col, 'activation not successful of id ', ''), 'activation successful of id ', '') as id from ....
[sorry can't tell from this edit screen if that's entirely valid sql]
That starts to get messy; you might consider creating a function and putting the replace statements in that.
If this is a one off job, it won't really matter. You could also use a regex, but that's quite slow (and in any case mean you now have 2 problems).