I have a table that has a column like the one below
url
----------------
dir=mp3\cat152AB&fileName=file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3
dir=mp3\cat4500f0655&fileName=file-03.mp3
...
How can I delete extra strings and arrange the fields as follows in SQL Server.
url
----------------
file-01
file-02
file-03
...
you can use charindex and substring :
SELECT substring ('dir=mp3\cat152AB&fileName=file-01.mp3', CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3') +9 ,
LEN('dir=mp3\cat152AB&fileName=file-01.mp3')-CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3')
) AS MatchPosition;
CHARINDEX and SUBSTRING can help you, please check the example:
select substring (field, charindex (';fileName=', field) + len (';fileName='), len (field) - len ('.mp3') + 1 - charindex (';fileName=', field) - len (';fileName='))
from (
select 'dir=mp3\cat152AB&fileName=file-01.mp3' field union all
select 'dir=mp3\cat2500DfDD00&fileName=file-02.mp3' union all
select 'dir=mp3\cat4500f0655&fileName=file-03.mp3'
) a
The information you want always seems to be the 11th to 5th characters before the end of the string. I would suggest a simple solution:
select left(right(url, 11), 7)
Here is a db<>fiddle.
Please try the following method.
It is using tokenization via XML/XQuery.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, url VARCHAR(255));
INSERT INTO #tbl (url) VALUES
('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = '=';
SELECT id, url
, LEFT(x, CHARINDEX('.', x) - 1) AS Result
FROM #tbl
CROSS APPLY (SELECT CAST('<root><r><![CDATA[' +
REPLACE(url, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(100)'))) AS t2(x);
Output
+----+------------------------------------------------+---------+
| id | url | Result |
+----+------------------------------------------------+---------+
| 1 | dir=mp3\cat152AB&fileName=file-01.mp3 | file-01 |
| 2 | dir=mp3\cat2500DfDD00&fileName=file-02.mp3 | file-02 |
| 3 | dir=mp3\cat4500f0655&fileName=file-03.mp3 | file-03 |
+----+------------------------------------------------+---------+
I know we have an accepted answer but I wanted to chime in with another simple, high-performing solution that addresses file names and file extensions with various lengths. For fun I included a parameter that allows you to include the file extension if you choose.
--==== Easily Consumable Sample Data
DECLARE #link TABLE ([url] VARCHAR(100) UNIQUE);
INSERT #link VALUES ('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3'),
('dir=mp3\cat4500f0655&fileName=file-999.mp3'),
('dir=mp3\cat4500d9997&fileName=file-0021.prodigi');
--==== Allows you to determine if you want the file extension
DECLARE #exclude BIT=1;
SELECT l.[url], TheFile = SUBSTRING(l.[url], s.Pos, s.Ln-s.Pos- ((#exclude*(fl.Ln)-1)))
FROM #link AS l
CROSS APPLY (VALUES(CHARINDEX('.',REVERSE(l.[url])))) AS fl(Ln)
CROSS APPLY (VALUES(CHARINDEX('fileName=',l.[url])+9, LEN(l.[url]))) AS s(Pos,Ln);
#exclude=1 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999
#exclude=0 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02.mp3
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021.prodigi
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03.mp3
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999.mp3
Related
I have an issue where I'm trying to remove all of the '.' from the string/filename below in SSMS apart from the last one which dictates file type.
EPC 14.10.14.pdf
Ideally I would like this string to appear as below:
EPC 141014.pdf
Any help would be appreciated
As a variable :
declare #doc varchar(30) = 'EPC 14.10.14.pdf'
declare #ext varchar(8) = right(#doc, charindex('.', reverse(#doc)));
set #doc = concat(replace(left(#doc,len(#doc)-len(#ext)),'.',''), #ext);
select #doc as doc;
doc
EPC 141014.pdf
As a table column :
create table test (
doc varchar(30) not null
);
insert into test (doc) values
('EPC 14.10.14.pdf'),
('FQD 15.11.15.jpeg');
select doc
, undotted_doc = concat(replace(left(doc, len(doc)-charindex('.', reverse(doc))),'.',''), right(doc, charindex('.', reverse(doc))))
from test;
doc
undotted_doc
EPC 14.10.14.pdf
EPC 141014.pdf
FQD 15.11.15.jpeg
FQD 151115.jpeg
Test on db<>fiddle here
Use replace,substring and len function
select replace(substring(#x,0,len(#x) - 3),'.','') + substring(#x,len(#x) - 3,len(#x))
EDIT:
If the name extension has a variable length, you can use the following query
select
CONCAT(
replace(substring(#x,0,len(#x) - CHARINDEX('.',TRIM(REVERSE(#x)))),'.','')
,
substring(#x,len(#x) - CHARINDEX('.',TRIM(REVERSE(#x))),len(#x))
)
Result
If you have extensions with different length (e.g. docx, xls), you need to find the index of the last occurrence of the . character using REVERSE() and CHARINDEX():
SELECT CONCAT(
REPLACE(SUBSTRING(SomeText, 1, LEN(SomeText) - CHARINDEX('.', REVERSE(SomeText))), '.', ''),
STUFF(SomeText, 1, LEN(SomeText) - CHARINDEX('.', REVERSE(SomeText)), '')
) AS FileName
FROM (VALUES
('EPC 14.10.14.pdf'),
('EPC 14.10.14.docx'),
('14.10.14.xlsx')
) t (SomeText)
Result:
FileName
----------------
EPC 141014.pdf
EPC 141014.docx
141014.xlsx
One more way.
SQL
SELECT fileName AS [Before]
, CONCAT(CONCAT(PARSENAME(fileName,4), PARSENAME(fileName,3), PARSENAME(fileName,2))
, '.', PARSENAME(fileName,1)) AS [After]
FROM (VALUES
('EPC 14.10.14.pdf'),
('EPC 14.10.14.docx'),
('14.10.14.xlsx'),
('csharp.10.14.cs')
) AS t(fileName);
Output
+-------------------+-----------------+
| Before | After |
+-------------------+-----------------+
| EPC 14.10.14.pdf | EPC 141014.pdf |
| EPC 14.10.14.docx | EPC 141014.docx |
| 14.10.14.xlsx | 141014.xlsx |
| csharp.10.14.cs | csharp1014.cs |
+-------------------+-----------------+
How to extract the value of clientid from the following xml document in Postgres?
I want to get value 1435 from this xml:
CREATE TABLE xmltest3(xtxt xml);
INSERT INTO xmltest3 values ('<clients><client clientId="1435"/></clients>');
SELECT unnest(xpath('./client /text()', xtxt::xml))::text AS XMLDATA FROM XMLTEST3;
I tried:
SELECT unnest(xpath('./clients/text()', xtxt::xml))::text AS XMLDATA
FROM XMLTEST3;
But it is not working.
Also, how to extract the ENvalues from this?
<ENList><EN ENValue="Liquidity"/><EN ENValue="Treasury"/></ENList>
Use #clientId to get the attribute value:
with invar as (
select '<clients><client clientId="1435"/></clients>'::xml as x
)
select unnest(xpath('/clients/client/#clientId', x))
from invar;
unnest
--------
1435
(1 row)
The concept is the same for your other example:
with invar as (
select '<ENList><EN ENValue="Liquidity"/><EN ENValue="Treasury"/></ENList>'::xml as x
)
select unnest(xpath('/ENList/EN/#ENValue', x))
from invar;
unnest
-----------
Liquidity
Treasury
(2 rows)
I need to insert multiple rows in a database table from a single string.
Here is my string it will be comma-seperated values
Current string:
batch 1 45665 987655,1228857 76554738,12390 8885858,301297 38998798
What I want is that batch 1 should be ignored or removed and remaining part should be added into the SQL Server database as a separate row for after each comma like this
Table name dbo.MSISDNData
Data
------------------
45665 987655
1228857 76554738
12390 8885858
301297 38998798
and when I query the table it should return the results like this
Query :
Select data
from dbo.MSISDNData
Results
Data
---------------------
45665 987655
1228857 76554738
12390 8885858
301297 38998798
Try this:
DECLARE #Data NVARCHAR(MAX) = N'batch 1 45665 987655,1228857 76554738,12390 8885858,301297 38998798'
DECLARE #DataXML XML;
SET #Data = '<a>' + REPLACE(REPLACE(#Data, 'batch 1 ', ''), ',', '</a><a>') + '</a>';
SET #DataXML = #Data;
SELECT LTRIM(RTRIM(T.c.value('.', 'VARCHAR(MAX)'))) AS [Data]
FROM #DataXML.nodes('./a') T(c);
It demonstrates how to split the data. You may need to sanitize it, too - remove the batch 1, perform trimming, etc.
I have below data in a column of a table, I want to split it into further columns.
| is used as the separator in this scenario . Column header should be before : & after column is its value.
Column
-----------------------------------------------------------------------------
ID: 30000300 | Name: India | Use: New Use
ID: 30000400 | Name: Aus | New ID: 15625616 | Address 1: NEW Rd
ID: 30000400 | Name: USA | City: VIA ARAMAC | New ID: 123
ID: 30000500 | Name: Russia | New ID: 15624951 | Address 2: 2131 BEAUDESERT
Output should be:
ID Name Use New ID City Address 1 Address 2 New City
----------------------------------------------------------------------
30000300 India New Use
30000400 Aus 15625616 NEW Rd
30000400 USA 15625616 VIA ARAMAC GALILEE
30000500 Russia 15624951 2131 BEAUDESERT
You have several rows that contain key value pairs inside an nvarchar column, but you want a table that has a header based on the keys and then rows containing just the values, sans keys. There is first the issue of an input like Key1: Value1 | Key2: Value2. Should this be returned as
Key1 Key2
Value1 NULL
NULL Value2
or is this not a possible scenario? Either way, there is the issue of generating a table with dynamic column names.
The problem with your question is that this is not a scenario that would normally be solved via SQL. You should get the data in your programming language of choice, then use regular expressions or split methods to get what you need.
If you insist doing it via SQL, then the solution is to turn the original lines input into another string, that you then sp_executesql (https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql), but I do NOT recommend it.
Here is a partial answer that you can use to return the n-th entry in a delimited string:
DECLARE #DelimitedString VARCHAR(8000);
DECLARE #Delimiter VARCHAR(100);
DECLARE #indexToReturn INT;
DECLARE #tblArray TABLE
(
ElementID INT IDENTITY(1, 1), -- Array index
Element VARCHAR(1000) -- Array element contents
);
-- Local Variable Declarations
-- ---------------------------
DECLARE #Index SMALLINT,
#Start SMALLINT,
#DelSize SMALLINT;
SET #DelSize = LEN(#Delimiter + 'x') - 1;
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(#DelimitedString) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #DelimitedString);
IF #Index = 0
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(#DelimitedString)));
BREAK;
END;
ELSE
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(SUBSTRING(#DelimitedString, 1, #Index - 1))));
SET #Start = #Index + #DelSize;
SET #DelimitedString = SUBSTRING(#DelimitedString, #Start, LEN(#DelimitedString) - #Start + 1);
END;
END;
DECLARE #val VARCHAR(1000);
SELECT #val = Element
FROM #tblArray AS ta
WHERE ta.ElementID = #indexToReturn;
SELECT #val;
So I have a lot of data like this:
pix11co;10.115.0.1
devapp087co;10.115.0.100
old_main-mgr;10.115.0.101
radius03co;10.115.0.110
And I want to delete the stuff after the ; so it just becomes
pix11co
devapp087co
old_main-mgr
radius03co
Since they're all different I can live with the semi-colon staying there.
I have the following query and it runs successfully but doesn't delete anything.
UPDATE dns$ SET [Name;] = REPLACE ([Name;], '%_;%__________%', '%_;');
What wildcards can I use to specify the characters after the ; ?
Can you use CHARINDEX? E.g.:
SELECT LEFT('pix11co;10.115.0.1', CHARINDEX(';', 'pix11co;10.115.0.1') - 1)
You can use SUBSTRING() and CHARINDEX() functions:
CREATE TABLE MyStrings (
STR VARCHAR(MAX)
);
INSERT INTO MyStrings VALUES
('pix11co;10.115.0.1'),
('devapp087co;10.115.0.100'),
('old_main-mgr;10.115.0.101'),
('radius03co;10.115.0.110');
SELECT STR, SUBSTRING(STR, 1, CHARINDEX(';', STR) -1 ) AS Result
FROM MyStrings;
Results:
+---------------------------+--------------+
| STR | Result |
+---------------------------+--------------+
| pix11co;10.115.0.1 | pix11co |
| devapp087co;10.115.0.100 | devapp087co |
| old_main-mgr;10.115.0.101 | old_main-mgr |
| radius03co;10.115.0.110 | radius03co |
+---------------------------+--------------+