Find value in comma-separated list - sql

I have lists like this stored in a field in SQL:
Id MyListField
1 soy, meat, milk, wheat, nuts
2 soy, meat, nuts, milk, wheat
3 nuts
4 walnuts, nutshell, nuts
5 nuts, beans
6 walnuts, hazel nuts
7 nutshell, nutsize
This is not normalized and I can't change it. I now have to find nuts and replace them with insane (but keep e. g. hazel nuts and nutshell).
A Find is relatively easy, there are four cases and I have the placeholder character % at my disposal:
SELECT * FROM MyTable WHERE
MyListField LIKE 'nuts' OR
MyListField LIKE 'nuts, %' OR
MyListField LIKE '%, nuts' OR
MyListField LIKE '%, nuts, %'
But a Replace is hard, because I don't have placeholder or startofstring/endofstring characters:
UPDATE MyTable SET MyListField =
REPLACE(
REPLACE(
REPLACE(
REPLACE(
MyListField,
', nuts, ' ,
', insane, '
),
????,
????
),
????,
????
),
????,
????
)
WHERE
MyListField LIKE 'nuts' OR
MyListField LIKE 'nuts, %' OR
MyListField LIKE '%, nuts' OR
MyListField LIKE '%, nuts, %'
I can easily replace it in the middle of the string, but not at the start or the end. Or can I?
I am using SQL Server 2008, if that matters.

If you concatenate the field between , and _, then you only have one case to look for.
e.g.
update MyTable set MyFieldList = replace(', ' + MyFieldList + ',', ', nuts,', ', insane,')
update MyTable set MyFieldList = substring(MyFieldList, 3, len(MyFieldList) - 3)

By putting a comma at the start and end of the list, each element is wrapped in a leading ", " and a trailing ",".
Then your replace method becomes easy....
REPLACE(', ' + MyListField + ',',
', ' + #termToReplace + ',',
', ' + #replacement + ',')
Finally, strip the leading and trailing commas.

You could use something like
case
when Field = #val then #replaceVal
when Field like #val + ', %' then
#replaceVal + substring(Field, len(#val) + 1, len(Field))
when Field like '%, ' + #val then
left(Field, len(Field) - len(#val)) + #replaceVal
Just add all the remaining options, and you should be fine.

With all that help, it was easier than I thought it to be.
UPDATE MyTable
SET MyListField =
SUBSTRING(
REPLACE(
CONCAT(', ', MyListField, ', '),
', nuts, ',
', insane, '
),
3,
DATALENGTH(MyListField)+LEN('insane')-LEN('nuts')
)
WHERE CONCAT(', ',MyListField,', ') LIKE '%, nuts, %'
This works as long as there is one or zero occurrences in the string. If there can be more than one, it will fail, but this does not matter to me. If it matters to you, feel free to multiply the (LEN-LEN) part with How do you count the number of occurrences of a certain substring in a SQL varchar?

Related

Modify/clean field values before applying a query filter in MongoDB like in SQL Server?

I have a SQL Server query that I need to convert into a Mongo Query. As we all know that we can clean up fields in SQL before applying conditions to them e.g
In the 3rd line we are applying ltrim,rtrim on the clinics field before applying the like condition to it. Same with the reverse field in the query multiple times. If this was a single step query I would have done something maybe using aggregation but this is a multistep cleanup using replace, convert, ltrim, rtrim etc in different places.
Can someone please throw some light on how I could convert it. If someone is an expert in this domain and can convert it into Mongo, that would be great as well. Thanks :)
select rule from rules where
isnull(status,0) = '1' AND isnull(deleted,0) = '0'
AND (((ltrim(rtrim(isnull(clinics,'0'))) like '0%') OR
( ',' + replace(replace(isnull(clinics,'0'),' ','') ,' ','') + ','
like '%,' + convert(varchar,"""+category+""") + ',%')) AND
(',' + replace(replace(isnull(clinics,'0'),' ','') ,' ','') + ','
not like '%,-' + replace(convert(varchar,"""+category+"""),' ','') + ',%')) AND
((( (ltrim(rtrim(isnull(reverse,'0'))) like '0%') OR
(( ','+ replace(replace(isnull(reverse,'0'),' ','') ,' ','') + ','
like '%,' + convert(varchar,"""+primary+""") + ',%')))
AND (',' + replace(replace(isnull(reverse,'0'),' ','') ,' ','') + ','
not like '%,-' + replace(convert(varchar,"""+primary+"""),' ','') + ',%') ))

Trim extra white space within column

I have the following select that is converting a name from Lastname, Firstname format into Firstname Lastname format. It seems to be adding extra white space between the first name and the last name
SELECT substring(D.NAME, charindex(',', replace(D.NAME, ' ', '')) + 1, len(D.NAME))
+ ' '
+ left(D.NAME, charindex(',', D.NAME) -1) AS First_Last
FROM TEST_TABLE D
Here are a few examples of the output I'm getting now:
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
Desired Format (single space between first and last name):
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
I tend to like this technique. In this example we use a rare replacement pattern of †‡, but you can use <> and ><
Note: The outer ltrim(rtrim( ... )) is optional, I keep it as a "just in case".
Example
Select NewValue = ltrim(rtrim(replace(replace(replace([Name],' ','†‡'),'‡†',''),'†‡',' ')))
From YourTable
Returns
NewValue
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
Maybe there are names with or without , or with or without spaces after the ,, or other inconsistencies.
Anyway you can use ltrim(rtrim()) before concatenating:
select
case
when d.name like '%,%' then
ltrim(rtrim(substring(d.name, charindex(',', name) + 1, len(d.name))))
+ ' ' +
ltrim(rtrim(left(D.NAME, charindex(',', d.name) -1)))
when d.name like '% %' then
ltrim(rtrim(substring(d.name, charindex(' ', name) + 1, len(d.name))))
+ ' ' +
ltrim(rtrim(left(D.NAME, charindex(' ', d.name) -1)))
else ltrim(rtrim(d.name))
end AS First_Last
Try:
select ltrim(rtrim(left(D.NAME, charindex(',', D.NAME, 0) - 1)))
+ ' '
+ ltrim(rtrim(right(D.NAME, len(D.NAME) - charindex(',', D.NAME, 0))))
from TEST_TABLE D
This worked on some test data I used below:
insert into #Test ([Name]) values ('Johnnyyy, Smithsonnn')
insert into #Test ([Name]) values ('Kimmey, Test1')
insert into #Test ([Name]) values ('Denise, Stuffing')
Which gives the intended result:
Johnnyyy Smithsonnn
Kimmey Test1
Denise Stuffing
I think you intend to do the replace of spaces after extracting the name. So:
SELECT (replace(left(D.NAME, charindex(',', D.NAME + ',') + 1), ' ', '') +
' ' +
left(D.NAME, charindex(',', D.NAME + ',') - 1)
) AS First_Last
FROM TEST_TABLE D;
This also adds a comma for the charindex() so the comma is optional.

How can I CONCAT portions of three columns to one new column

I am trying to create a new column in my results that is made up on the first 3 characters of "PrimaryName", all of "VendorCity", and the first 5 characters of "VendorZip"
SELECT,VendorName
,replace(PrimaryVendorLocationName,' ','') as PrimaryName
,replace(PrimaryVendorLocationCity,' ','') as VendorCity
,replace(PrimaryVendorLocationZipCode,' ','') as VendorZip
FROM [table]
As you can see I also need to remove spaces to ensure a cleaner return. I would like to call the new column "NewVendorCode". So a record that originates like this:
R A Slack
Chicago Heights
60654-1234
Will return this:
RASChicagoHeights60654
You can use the following, using LEFT (MySQL / TSQL):
SELECT CONCAT(
LEFT(REPLACE(PrimaryVendorLocationName, ' ', ''), 3),
REPLACE(PrimaryVendorLocationCity, ' ', ''),
LEFT(REPLACE(PrimaryVendorLocationZipCode, ' ', ''), 5)
) FROM table_name
... or you can use SUBSTRING (MySQL / TSQL) (instead of LEFT):
SELECT CONCAT(
SUBSTRING(REPLACE(PrimaryVendorLocationName, ' ', ''), 1, 3),
REPLACE(PrimaryVendorLocationCity, ' ', ''),
SUBSTRING(REPLACE(PrimaryVendorLocationZipCode, ' ', ''), 1, 5)
) FROM table_name
Note: As you can see the SELECT querys work on MySQL and TSQL without change.
demo (MySQL): https://www.db-fiddle.com/f/wTuKzosFgkEuKXtruCTCxg/0
demo (TSQL): http://sqlfiddle.com/#!18/dbc98/1/1
You can use the following code:
SELECT VendorName+
replace(PrimaryVendorLocationName,' ','') +
replace(PrimaryVendorLocationCity,' ','') +
replace(PrimaryVendorLocationZipCode,' ','') as NewVendorCode
SELECT VendorName
,PrimaryName
,VendorCity
,VendorZip
,CONCAT(LEFT(PrimaryName,3),VendorCity,LEFT(VendorZip,5)) As NewVendorCode
FROM (
SELECT VendorName
,replace(PrimaryVendorLocationName,' ','') as PrimaryName
,replace(PrimaryVendorLocationCity,' ','') as VendorCity
,replace(PrimaryVendorLocationZipCode,' ','') as VendorZip
FROM [table]
)

Replacing multiple items(commas, periods, etc.) in SQL code

Here is the code that I am using currently, I am trying to replace commas and periods in my database but right now it is only doing one or the other. Thanks
(Case when dim.obligorname like '%,%' then Replace(DIM.[ObligorName], ',', ' ')
Else case when dim.obligorname like '%.%' then Replace(DIM.[ObligorName], '.', ' ')
Else Dim.ObligorName end end) as Obligorname,
Why not just try something like this:
UPDATE myTable DIM
SET DIM.[ObligorName] =
Replace(Replace(DIM.[ObligorName], ',', ' '), '.', ' ')
How about something like this:
Replace( Replace(DIM.[ObligorName], ',', ' '), '.', ' ')

Concatenate and format text in SQL

I need to concatenate the City, State and Country columns into something like City, State, Country.
This is my code:
Select City + ', ' + State + ', ' + Country as outputText from Places
However, because City and State allow null (or empty) value, what happen is, (for example) if the City is null/empty, my output will look like , Iowa, USA; or say the State is empty, then the output will look like Seattle, , USA
Is there anyway I can format the output and remove "unnecessary" commas?
Edited: Because of the requirements, I should not use any other mean (such as PL/SQL, Store Procedure) etc., so it has to be plain SQL statement
select
isnull(City, '') +
case when isnull(City, '') != '' then ', ' else '' end +
isnull(State, '') +
case when isnull(State, '') != '' then ', ' else '' end +
isnull(Country, '') as outputText
from
Places
Since adding a string with null will result null so if they are null (not empty string) this will give you teh desired result
Select isnull(City + ', ','') + isnull(State + ', ' ,'') + isnull(Country,'') as outputText from Places
Use the COALESCE (Transact-SQL) function.
SELECT COALESCE(City + ', ', '') + COALESCE(State + ', ', '')...
In SQL Server 2012 you can use CONCAT function:
select concat(City,', ',State,', ',Country ) as outputText from Places
Not elegant by any means...
first changes city, state,country to null values if blank
then interprets that value for null and adds a space before a comma
then replaces any space comma space ( , ) with empty set.
Query:
SELECT replace(coalesce(Replace(City,'',Null),' ') + ', ' +
coalesce(Replace(State,'',Null), ' ' + ', ' +
coalesce(replace(Country,''Null),''), ' , ','') as outputText
FROM Places
Assumes no city state or country will contain space comma space.