Select subset of delimited string field - sql-server

My table has a field with data formatted like this:
Term 1~Term 2~Term 3~Term 4~Term 5~Term 6~
All non-blank values contain 6 tilde-separated strings, which may be several words long.
I need to extract the last 2 substrings from this field as part of a query.I'm not interested in splitting the data into multiple records, and I don't have permissions to create a stored procedure.
Thanks in advance for any advice.

DECLARE #Term VARCHAR(100)
SELECT #Term = 'abc~def~ghi~jkl~mno~pqr~'
SELECT RIGHT(#Term, CHARINDEX('~',REVERSE(#Term),CHARINDEX('~',REVERSE(#Term),2)+1)-1)
That will give the last two terms with ~ intact. Note you can wrap REPLACE() around that to put something other than the tilde in there.

another way to do is this.. use string_split (in 2016) or an equivalent UDF that can be found elsewhere.. to split the string
declare #term varchar(100) = 'abc~def~ghi~jkl~mno~pqr~'
; with mycte as (
select
value as string_value
, row_number() over (order by (select 1000) )as row_num
from string_split(#term,'~'))
select top 2 string_value
from mycte
where string_value<>''
order by row_num desc

Related

Regular Expressions in SQL Server to validate fax numbers

I'm trying to use RegEx to validate phone numbers saved in a SQL Server 2016 Table. In this table there are thousands of fax numbers which stored as different formats. Ex : 800-123-4567, 800/123-4567, 800#123/4567 etc. Now I'm wanting to use RegEx to validate the phone numbers also output them in a way without any special characters or spaces in between. Ex : 8001234567.
Here's what I have tried which does not seems to work for some reason. If anyone out there could correct me what I'm doing wrong here, I would really appreciate it.
DECLARE #expres VARCHAR(50) = '%[/,-,\,#]%'
DECLARE #cmpfax as CHAR(100);
SELECT #cmpfax = cmp_fax FROM cicmpy WHERE LTRIM(RTRIM(cmp_code)) = '100373' AND cmp_fax IS NOT NULL;
SELECT REPLACE(#cmpfax, #expres, '#');
Here's my dbfiddle for the above code which I've tested.
This is a variation on the answer I linked earlier, however, as the OP is on 2016 RTM, they can't use STRING_AGG. This, therefore, uses the "old" FOR XML PATH (and STUFF) method to reaggregate the characters.
CREATE OR ALTER FUNCTION [fn].[PatternCharacterReplace_XML] (#String varchar(8000), #Pattern varchar(100), #ReplacementCharacter varchar(1))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP(LEN(#String))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4)
SELECT (SELECT CASE WHEN V.C LIKE #Pattern THEN #ReplacementCharacter ELSE V.C END
FROM Tally T
CROSS APPLY (VALUES(SUBSTRING(#String,T.I,1)))V(C)
ORDER BY T.I
FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(8000)') AS ReplacedString;
Then you get the values and remove the characters with something like this:
SELECT YT.Fax
PCRX.ReplacedString AS NewFax
FROM dbo.YourTable YT
CROSS APPLY fn.PatternCharacterReplace_XML(YT.Fax, '[^0-9]', '') PCRX
WHERE YT.Fax LIKE '%[^0-9]%';

SQL Server : Replace (Charindex)

I have a SQL Server table with numbers in column no:
12345670000115
14245670000116
58492010000118
I need a function that will remove one number 1 from right side of number, so result must be like:
1234567000015
1424567000016
5849201000018
I find some solutions to use charindex() with substring(), but my SQL skills are poor so I really need help.
Thanks
Assuming this is varchar data here is an easy way to accomplish this. BTW, I would suggest you not use column names like 'no'. It is a reserved word and it is horribly ambiguous. Does that mean number or the opposite of yes? If it is number as I assume it would be better to name the column with an indication of what the number is. PartNumber, ItemNumber, CatalogNumber whatever...
LEFT(no, len(no) - 2) + RIGHT(no, 1)
Try to use this query:
declare #charToReplace char = '1'
select REVERSE(stuff(REVERSE(no), charindex(#charToReplace, REVERSE(no)), 1, ''))
from table
or
declare #charToReplace char = '1'
declare #tmp_table TABLE (NO varchar(16))
insert into #tmp_table
select REVERSE(NO)
from yourtable
select REVERSE(stuff(NO, charindex(#charToReplace, NO), 1, ''))
For your particular data, if the numbers fit a BIGINT, one easy way is to treat them like numbers:
Setup
create table #tmp (
number VARCHAR(16)
)
insert into #tmp values ('12345670000115'), ('14245670000116'), ('58492010000118')
GO
Script:
select number, cast( (cast(number AS bigint) - 100) / 100 * 10 + cast(number AS bigint) % 100 as VARCHAR(16))
from #tmp
GO
I resolve problem. There is answer in which I remove one character 1 and update whole table. Thanks all for help!
Update myTableName
set barcode=substring(barcode,1,11)+substring(barcode,13,1)
where len(barcode)>= 14

How to send a comma delimited string of integers as a parameter list in sql server?

In this sql server stored procedure query
SELECT HireResponseID,
HireResponse,
DateResponse,
Comments,
YearFileOpened,
file_number,
isCaseOpen,
last_update,
isConfidential,
date_created,
OurClient,
TheirClient,
ProjectName,
description,
lawyer_lastname,
lawyer_firstname,
Conflicts.ConflictID
FROM Hire_Response,
Conflicts,
Lawyers
WHERE Hire_Response.ConflictID=Conflicts.ConflictID
AND Lawyers.lawyerID=Conflicts.lawyerID
AND firmID = #FirmID
AND HireID IN #HireID
AND isStillaConflict = 1
ORDER BY file_number,
TheirClient,
OurClient,
lawyer_lastname,
lawyer_firstname
The parameter #HireID is a string of comma delimited integers (it doesn't have brackets around it). I want to check if the HireID integer is in the #HireID string. But I don't know how to parse this.
Can anyone help please?
Thanks
If I understand your question, you want to find rows where HireID is in the list #HireID. If the HireID is a consistent length, and the list is delimited, then you could use this:
AND #HireID LIKE '%'+CAST(HireID AS VARCHAR(5))+'%'
You could also use CHARINDEX:
AND CHARINDEX(HireID,#HireID) > 0
Edit: To account for inconsistent length, you could use:
AND (#HireID LIKE '%'+CAST(HireID AS VARCHAR(5))+',%'
OR #HireID LIKE '%,'+CAST(HireID AS VARCHAR(5))+'%')
Try this one -
DECLARE #HireID VARCHAR(100)
SELECT #HireID = '2,18'
;WITH cte AS
(
SELECT ID = t.c.value('.', 'INT')
FROM (
SELECT txml = CAST('<t>' + REPLACE(#HireID, ',', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY txml.nodes('/t') AS t(c)
)
SELECT *
FROM Hire_Response
JOIN Conflicts ON Hire_Response.ConflictID = Conflicts.ConflictID
JOIN Lawyers ON Lawyers.lawyerID = Conflicts.lawyerID
WHERE firmID = #FirmID
AND isStillaConflict = 1
AND HireID in (SELECT ID FROM cte)
ORDER BY file_number, TheirClient, OurClient, lawyer_lastname, lawyer_firstname

How to split a string after specific character in SQL Server and update this value to specific column

I have table with data 1/1 to 1/20 in one column. I want the value 1 to 20 i.e value after '/'(front slash) is updated into other column in same table in SQL Server.
Example:
Column has value 1/1,1/2,1/3...1/20
new Column value 1,2,3,..20
That is, I want to update this new column.
Try this:
UPDATE YourTable
SET Col2 = RIGHT(Col1,LEN(Col1)-CHARINDEX('/',Col1))
Please find the below query also split the string with delimeter.
Select Substring(#String1,0,CharIndex(#delimeter,#String1))
From: http://www.sql-server-helper.com/error-messages/msg-536.aspx
To use function LEFT if not all data is in the form '1/12' you need this in the second line above:
Set Col2 = LEFT(Col1, ISNULL(NULLIF(CHARINDEX('/', Col1) - 1, -1), LEN(Col1)))
SELECT SUBSTRING(ParentBGBU,0,CHARINDEX('-',ParentBGBU,0)) FROM dbo.tblHCMMaster;
I know this question is specific to sql server, but I'm using postgresql and came across this question, so for anybody else in a similar situation, there is the split_part(string text, delimiter text, field int) function.
Maybe something like this:
First some test data:
DECLARE #tbl TABLE(Column1 VARCHAR(100))
INSERT INTO #tbl
SELECT '1/1' UNION ALL
SELECT '1/20' UNION ALL
SELECT '1/2'
Then like this:
SELECT
SUBSTRING(tbl.Column1,CHARINDEX('/',tbl.Column1)+1,LEN(tbl.Column1))
FROM
#tbl AS tbl
SELECT emp.LoginID, emp.JobTitle, emp.BirthDate, emp.ModifiedDate ,
CASE WHEN emp.JobTitle NOT LIKE '%Document Control%' THEN emp.JobTitle
ELSE SUBSTRING(emp.JobTitle,CHARINDEX('Document Control',emp.JobTitle),LEN('Document Control'))
END
,emp.gender,emp.MaritalStatus
FROM HumanResources.Employee [emp]
WHERE JobTitle LIKE '[C-F]%'
Use CHARINDEX. Perhaps make user function. If you use this split often.
I would create this function:
CREATE FUNCTION [dbo].[Split]
(
#String VARCHAR(max),
#Delimiter varCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'INT_COLUMN' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'STRING_COLUMN' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO

Reporting Services - String Length being changed with UNION ALL T-SQL

I have one data_source returning 2 rows from a query with one string with 8chars and another with 11chars. I'm really sure that one of the strings has 8 chars because i explicit put it in the where condition( something like this . where name = 'ftcc_ppp') .The truth is that reporting services is adding some extra blank chars and is fixing the length of the string to the max(length string of all the resultset without the where condition).
I wanted to make some filters and was having the wrong results because the string was not with 8 chars, but instead with 11 chars(8 + 3blank).
The where condition is done in a sub-query that has in that field one row with 8 chars and another with 11 chars(ftcc_ppp and ftcc_ppp_lx).
why reporting services act like this ? Any explanation?
Thank you all
EDIT: Query code:
BEGIN
DECLARE #dtDate DATETIME
DECLARE #lastDay DATE;
DECLARE #firstDay DATE;
DECLARE #currentDate DATE;
DECLARE #month_table AS TABLE(DATA DATE);
SET #dtDate = #DATA;
SET #lastDay = CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#dtDate)+1,0)) AS DATE)
SET #firstDay = DATEADD(d,-DAY(#dtDate)+1,#dtDate);
SET #currentDate = #firstDay;
WHILE #currentDate <> dateadd(d,1,#lastDay)
BEGIN
PRINT #currentDate;
INSERT INTO #month_table VALUES(#currentDate);
SET #currentDate = dateadd(d,1,#currentDate);
END
SELECT * FROM (
SELECT DATA,motivo,SUM(total) AS total,CAST(campanha AS VARCHAR(11)) AS campanha,[TYPE]
FROM [Client].[dbo].[ftcc_ppp_motivo_nelegivel_totais]
GROUP BY DATA,motivo,campanha,[TYPE]
UNION ALL
SELECT DATA,motivo,0 AS total,CAST('ftcc_ppp' AS VARCHAR(11)) campanha,'LOP' AS [TYPE]
FROM #month_table
CROSS JOIN dbo.ftcc_ppp_motivo_nelegivel_keys
UNION ALL
SELECT DATA,motivo,0 AS total,CAST('ftcc_ppp' AS VARCHAR(11)) campanha,'ALOP' AS [TYPE]
FROM #month_table
CROSS JOIN dbo.ftcc_ppp_motivo_nelegivel_keys
UNION ALL
SELECT DATA,motivo,0 AS total,CAST('ftcc_ppp_lx' AS VARCHAR(11)) campanha,'CARD' AS [TYPE]
FROM #month_table
CROSS JOIN dbo.ftcc_ppp_motivo_nelegivel_keys
) xpto
WHERE campanha = 'ftcc_ppp'
END
I found the issue!! :) :)
The problem was in the hardcoded string.
Apparently hardcoded strings is a char type. So i had one char with 8 plus one char with 11.
The result obvious was 11 chars.
Using the len() in SQL SERVER i couldn't find the blank spaces inserted because SQLSERVER automatically removes the blank chars. When editing the rows inside SQL SERVER the cursor shown me the blank spaces. Great Lesson :)
Thank you all for the time given to my problem.
It was a pleasure to utilize for the first time StackOverflow.
Thank you all.
Greetings.
Another possible cause: Check your database compatibility level. If set to 80 you may have an issue, but 90 (or higher?) you wouldn't.
According to:
http://msdn.microsoft.com/en-us/library/bb510680.aspx
The UNION of a variable-length column and a fixed length column
produces a fixed-length column.

Resources