how to separate text from integer - sql-server-2005

I have addresses:
ALKOŅU 3-20;
M.LUBŠNAS 16V-9;
STIEBRU 6-22;
ANDREJA UPĪĀA IELA 16-2;
MISNKAS 4 -115;
CISKADI,BAZNICAS 4;
How it is possible in sql to separate first text part (district) from integer (house and flat number)?

Assuming the break-point is ALWAYS the first digit, then
SELECT RTRIM(LEFT(col, PATINDEX('%[0-9]%', col + '0') -1)) as District,
STUFF(col, 1, PATINDEX('%[0-9]%', col + '0') -1, '') as HouseAndFlat
FROM ...
e.g.
with t(col) as (
select
'ALKOŅU 3-20' union all select
'M.LUBŠNAS 16V-9' union all select
'STIEBRU 6-22' union all select
'ANDREJA UPĪĀA IELA 16-2' union all select
'MISNKAS 4 -115' union all select
'CISKADI,BAZNICAS 4')
SELECT RTRIM(LEFT(col, PATINDEX('%[0-9]%', col + '0') -1)) as District,
STUFF(col, 1, PATINDEX('%[0-9]%', col + '0') -1, '') as HouseAndFlat
FROM t

Related

Regex values after special character with empty values

I am struggle with regex to split spring into columns in Oracle database.
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '[^: ]+', 1, 4)) from dual;
I need to obtain 4th value from that string as a column value, sometimes values at position 2,3 are empty and my query doesn't work. I am trying to figure out what regex will work
You can use
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '([^: ]*)(:|$)', 1, 4, 'i', 1)) from dual;
Here, the ([^: ]*)(:|$) matches
([^: ]*) - Group 1: any zero or more chars other than : and space
(:|$) - Group 2, either : or end of string.
You do not need a (slower) regex for this task, use simple substr/instr functions:
with input_(val) as (
select '1:::9999' from dual
union all
select '1:2::' from dual
union all
select '1:2::3:5' from dual
)
, replaced as (
select input_.*, replace(val, ' ', '') as val_replaced
from input_
)
select
val,
substr(
val_replaced,
/*Locate the first occurrence of a colon and get a substring ...*/
instr(val_replaced, ':', 1, 3) + 1,
/*.. until the end, if the next colon is absent, or until the next colon*/
nvl(nullif(instr(val_replaced, ':', 1, 4), 0), length(val_replaced) + 1) - instr(val_replaced, ':', 1, 3) - 1
) as col
from replaced
VAL
COL
1:::9999
9999
1:2::
null
1:2::3:5
3
fiddle with performance difference.

I need to Update my row with english version

I have a column which includes rows like this : MER.Fiyatlandırma Müdür Yardımcısı.
SELECT name, SUBSTR(
name,
INSTR(name, '.', 1, 1),
INSTR(name, '.', 1, 2) + 1 - INSTR(name, '.', 1, 1)
) AS deneme
FROM HR_ALL_POSITIONS_F;
I used this code and my rows looks like .Fiyatlandırma Müdür Yardımcısı.
Also ı have an excel file which includes .Fiyatlandırma Müdür Yardımcısı. this row and english version.
I need to change .Fiyatlandırma Müdür Yardımcısı. this to Price Vice Manager.
How can ı do that.
UPDATE denememusa123
SET denememusa123.eklenecekkolon = (SELECT ENGLISHPOSITION FROM pozisyontanimlama)
WHERE (SELECT SUBSTR (name,
INSTR (name,
'.',
1,
1),
INSTR (name,
'.',
1,
2)
+ 1
- INSTR (name,
'.',
1,
1))
FROM HR_ALL_POSITIONS_F) = (Select TURKISHPOSITION FROM pozisyontanimlama);
(I tired this but it is not working.
ora-01427:single-row subquery returns more than one row )
Help Please.
You can use a MERGE statement:
MERGE INTO denememusa123 dst
USING (
WITH split_denememusa123 (rid, prefix, position, suffix) AS (
SELECT rowid AS rid,
SUBSTR(
eklenecekkolon,
1,
INSTR(eklenecekkolon, '.', 1, 1)
) AS prefix,
SUBSTR(
eklenecekkolon,
INSTR(eklenecekkolon, '.', 1, 1) + 1,
INSTR(eklenecekkolon, '.', 1, 2) - INSTR(eklenecekkolon, '.', 1, 1) - 1
) AS position,
SUBSTR(
eklenecekkolon,
INSTR(eklenecekkolon, '.', 1, 2)
) AS suffix
FROM denememusa123
WHERE INSTR(eklenecekkolon, '.', 1, 2) > 0
)
SELECT s.rid, s.prefix || p.englishposition || s.suffix AS position
FROM split_denememusa123 s
INNER JOIN pozisyontanimlama p
ON (p.turkishposition = s.position)
) src
ON (src.rid = dst.ROWID)
WHEN MATCHED THEN
UPDATE SET dst.eklenecekkolon = src.position;
Which, for the sample data:
CREATE TABLE denememusa123 (eklenecekkolon) AS
SELECT 'MER.Fiyatlandırma Müdür Yardımcısı.XYZ' FROM DUAL;
CREATE TABLE pozisyontanimlama (turkishposition, englishposition) AS
SELECT 'Fiyatlandırma Müdür Yardımcısı', 'Price Vice Manager' FROM DUAL
Then after the MERGE the table contains:
EKLENECEKKOLON
MER.Price Vice Manager.XYZ
fiddle

bigquery: find following row matching condition

I'm looking at text sequences in BigQuery and trying to identify word completions over a number of rows (sharing an ID). The data looks like:
ID, Text
1, t
1, th
1, the
1, the
1, the c
1, the ca
1, the cat
1, the cat
1, the cat s
...
1, the cat sat on the mat
2, r
...
For each given ID and sequence i'm trying to find the next word boundary. So the ideal output would be:
ID, Text, Boundary
1, t, the
1, th, the
1, the c, the cat
1, the ca, the cat
1, the cat s, the cat sat
In the above the next subsequent row that both shares an ID and ends in a space gives the next (there can be multiple) word completion boundary.
Below is for BigQuery Standard SQL
Note: it is brute force approach so query is not that elegant as potentially can be - but hope this will give you good start
#standardSQL
SELECT id, item, boundary
FROM (
SELECT id, grp,
STRING_AGG(IF(boundary, text, ''), '') boundary,
ARRAY_AGG(IF(NOT boundary, text, NULL) IGNORE NULLS ORDER BY LENGTH(text)) items
FROM (
SELECT id, text,
LENGTH(text) - LENGTH(REPLACE(text, ' ', '')) - IF(SUBSTR(text, -1) = ' ', 1, 0) grp,
SUBSTR(text, -1) = ' ' boundary
FROM `project.dataset.table`
)
GROUP BY id, grp
), UNNEST(items) item WITH OFFSET pos
WHERE RTRIM(item) != RTRIM(boundary)
if to apply to dummy data in your question as below
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, 't' text UNION ALL
SELECT 1, 'th' UNION ALL
SELECT 1, 'the' UNION ALL
SELECT 1, 'the ' UNION ALL
SELECT 1, 'the c' UNION ALL
SELECT 1, 'the ca' UNION ALL
SELECT 1, 'the cat' UNION ALL
SELECT 1, 'the cat ' UNION ALL
SELECT 1, 'the cat s' UNION ALL
SELECT 1, 'the cat sat '
)
SELECT id, item, boundary
FROM (
SELECT id, grp,
STRING_AGG(IF(boundary, text, ''), '') boundary,
ARRAY_AGG(IF(NOT boundary, text, NULL) IGNORE NULLS ORDER BY LENGTH(text)) items
FROM (
SELECT id, text,
LENGTH(text) - LENGTH(REPLACE(text, ' ', '')) - IF(SUBSTR(text, -1) = ' ', 1, 0) grp,
SUBSTR(text, -1) = ' ' boundary
FROM `project.dataset.table`
)
GROUP BY id, grp
), UNNEST(items) item WITH OFFSET pos
WHERE RTRIM(item) != RTRIM(boundary)
ORDER BY id, grp, pos
result is
Row id item boundary
1 1 t the
2 1 th the
3 1 the c the cat
4 1 the ca the cat
5 1 the cat s the cat sat
BigQuery UDF's come in handy in these situations. Here is a working solution:
#standardSQL
/*boundary function*/
create temp function boundaryf (text string, sentence string) as (
array_to_string(array(
select q.w from unnest(
array(select struct(w as w, row_number() over () as i) from unnest(split(sentence, ' ')) w
)
) q
-- respect the ending space
where q.i <= array_length(split(text, ' ')) - (length(text) - length(rtrim(text)))
), ' ')
);
WITH items AS (
#--your data. assuming this is already ordered
SELECT 1 as id, 't' as text UNION ALL
SELECT 1, 'th' UNION ALL
SELECT 1, 'the' UNION ALL
SELECT 1, 'the ' UNION ALL
SELECT 1, 'the c' UNION ALL
SELECT 1, 'the ca' UNION ALL
SELECT 1, 'the cat' UNION ALL
SELECT 1, 'the cat ' UNION ALL
SELECT 1, 'the cat s' UNION ALL
SELECT 1, 'the cat sa' union all
SELECT 1, 'the cat sat' union all
SELECT 1, 'the cat sat ' union all
SELECT 1, 'the cat sat o' union all
SELECT 1, 'the cat sat on' union all
SELECT 1, 'the cat sat on ' union all
SELECT 1, 'the cat sat on a' union all
SELECT 1, 'the cat sat on a ' union all
SELECT 1, 'the cat sat on a m' union all
SELECT 1, 'the cat sat on a ma' union all
SELECT 1, 'the cat sat on a mat' union all
select 2, 'i' union all
select 2, 'i a' union all
select 2, 'i am' union all
select 2, 'i am f' union all
select 2, 'i am fr' union all
select 2, 'i am fre' union all
select 2, 'i am free'
),
sentences as (
select id, sentences[offset (array_length(sentences)-1)] as sentence from (
select id, array_agg(text) as sentences
from items group by 1
)
),
control as (
select i.id, i.text, boundaryf(i.text, s.sentence) as boundary
from items i
left join sentences s on s.id = i.id
)
select * from control

Concatenating various characters

I have a series of ID numbers like this
ABC/12345/2012
DEF/67891/2013
GHI/23456/2014
KLM/78911/2014
I need to change them so they look like this
12-12345
13-67891
14-23456
14-78911
14-6634
The below works to a degree but I have a few that only have 4 numbers in, they should be proceeded by a zero.
SELECT RIGHT(ID, 2)+'-'+RIGHT(SUBSTRING(ID, CHARINDEX('/', ID, 1)-1, LEN(ID)-7), 5)
12-12345
13-67891
14-23456
14-78911
14-/6634
So I need 14-/6634 to look like 14-06634
Assuming your column name is ID, and length of each substrings between the '/' characters is not variable (ABC = 3, 12345 = 5, 2012 = 4):
SELECT RIGHT(ID, 2)+'-'+RIGHT(SUBSTRING(ID, CHARINDEX('/', ID, 1)-1, LEN(ID)-7), 5)
Based on your main post edit:
SELECT RIGHT(ID, 2)+'-'+REPLACE(RIGHT(SUBSTRING(ID, CHARINDEX('/', ID, 1)-1, LEN(ID)-7), 5), '/', '0')
Try this
declare #tmp varchar(50) = 'ABC/12345/2012'
select SUBSTRING(#tmp, len(#tmp) - 1, 2) + '-' + SUBSTRING(#tmp,CHARINDEX('/',#tmp)+1,LEN(#tmp))
it gives you
12-12345/2012
and now you have to remove /2012
If your data is fixed format, then you can use PARSENAME
Sample execution with sample data:
DECLARE #TestTable TABLE (TestData VARCHAR (50));
INSERT INTO #TestTable (TestData)
SELECT 'ABC/12345/2012' UNION
SELECT 'DEF/67891/2013' UNION
SELECT 'GHI/23456/2014' UNION
SELECT 'KLM/78911/2014'
SELECT RIGHT(PARSENAME(REPLACE(TestData, '/', '.'), 1), 2) + '-' +
PARSENAME(REPLACE(TestData, '/', '.'), 2) AS TestData
FROM #TestTable
Result:
TestData
--------
12-12345
13-67891
14-23456
14-78911

Pad Zero before first hypen and remove spaces and add BA and IN

I have data as below
98-45.3A-22
104-44.0A-23
00983-29.1-22
01757-42.5A-22
04968-37.3A2-23
Output Looking for output as below in SQL Server
00098-BA45.3A-IN-22
00104-BA44.0A-IN-23
00983-BA29.1-IN-22
01757-BA42.5A-IN-22
04968-BA37.3A2-IN-23
I splitted parts to cope with tricky data templates. This should work even with non-dash-2-digit tail:
WITH Src AS
(
SELECT * FROM (VALUES
('98-45.3A-22'),
('104-44.0A-23'),
('00983-29.1-22'),
('01757-42.5A-22'),
('04968-37.3A2-23')
) T(X)
), Parts AS
(
SELECT *,
RIGHT('00000'+SUBSTRING(X, 1, CHARINDEX('-',X, 1)-1),5) Front,
'BA'+SUBSTRING(X, CHARINDEX('-',X, 1)+1, 2) BA,
SUBSTRING(X, PATINDEX('%.%',X), LEN(X)-CHARINDEX('-', REVERSE(X), 1)-PATINDEX('%.%',X)+1) P,
SUBSTRING(X, LEN(X)-CHARINDEX('-', REVERSE(X), 1)+1, LEN(X)) En
FROM Src
)
SELECT Front+'-'+BA+P+'-IN'+En
FROM Parts
It returns:
00098-BA45.3A-IN-22
00104-BA44.0A-IN-23
00983-BA29.1-IN-22
01757-BA42.5A-IN-22
04968-BA37.3A2-IN-23
Try this,
DECLARE #String VARCHAR(100) = '98-45.3A-22'
SELECT ISNULL(REPLICATE('0',6 - CHARINDEX('-',#String)),'') -- Add leading Zeros
+ STUFF(
STUFF(#String,CHARINDEX('-',#String),1,'-BA'), -- Add 'BA'
CHARINDEX('-',#String,CHARINDEX('-',#String)+1)+2, -- 2 additional for the character 'BA'
1,'-IN') -- Add 'IN'
What if I have more than 6 digit number before first hyphen and want to remove the leading zeros to make it 6 digits.
DECLARE #String VARCHAR(100) = '0000098-45.3A-22'
SELECT CASE WHEN CHARINDEX('-',#String) <= 6
THEN ISNULL(REPLICATE('0',6 - CHARINDEX('-',#String)),'') -- Add leading Zeros
+ STUFF(
STUFF( #String,CHARINDEX('-',#String),1,'-BA'), -- Add 'BA'
CHARINDEX('-',#String,CHARINDEX('-',#String)+1)+2, -- 2 additional for the character 'BA'
1,'-IN') -- Add 'IN'
ELSE STUFF(
STUFF(
STUFF(#String,CHARINDEX('-',#String),1,'-BA'), -- Add 'BA'
CHARINDEX('-',#String,CHARINDEX('-',#String)+1)+2, -- 2 additional for the character 'BA'
1,'-IN'), -- Add 'IN'
1, CHARINDEX('-',#String) - 6, '' -- remove extra leading Zeros
)
END
Making assumptions that the format is consistent (e.g. always ends with "-" + 2 characters....)
DECLARE #Data TABLE (Col1 VARCHAR(100))
INSERT #Data ( Col1 )
SELECT Col1
FROM (
VALUES ('98-45.3A-22'), ('104-44.0A-23'),
('00983-29.1-22'), ('01757-42.5A-22'),
('04968-37.3A2-23')
) x (Col1)
SELECT RIGHT('0000' + LEFT(Col1, CHARINDEX('-', Col1) - 1), 5)
+ '-BA' + SUBSTRING(Col1, CHARINDEX('-', Col1) + 1, CHARINDEX('.', Col1) - CHARINDEX('-', Col1))
+ SUBSTRING(Col1, CHARINDEX('.', Col1) + 1, LEN(Col1) - CHARINDEX('.', Col1) - 3)
+ '-IN-' + RIGHT(Col1, 2)
FROM #Data
It's not ideal IMO to do this string manipulation all the time in SQL. You could shift it out to your presentation layer, or store the pre-formatted value in the db to save the cost of this every time.
Use REPLICATE AND CHARINDEX:
Replicate: will repeat given character till reach required count specify in function
CharIndex: Finds the first occurrence of any character
Declare #Data AS VARCHAR(50)='98-45.3A-22'
SELECT REPLICATE('0',6-CHARINDEX('-',#Data)) + #Data
SELECT
SUBSTRING
(
(REPLICATE('0',6-CHARINDEX('-',#Data)) +#Data)
,0
,6
)
+'-'+'BA'+ CAST('<x>' + REPLACE(#Data,'-','</x><x>') + '</x>' AS XML).value('/x[2]','varchar(max)')
+'-'+ 'IN'+ '-' + CAST('<x>' + REPLACE(#Data,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)')
In another way by using PARSENAME() you can use this query:
WITH t AS (
SELECT
PARSENAME(REPLACE(REPLACE(s, '.', '###'), '-', '.'), 3) AS p1,
REPLACE(PARSENAME(REPLACE(REPLACE(s, '.', '###'), '-', '.'), 2), '###', '.') AS p2,
PARSENAME(REPLACE(REPLACE(s, '.', '###'), '-', '.'), 1) AS p3
FROM yourTable)
SELECT RIGHT('00000' + p1, 5) + '-BA' + p2 + '-IN-' + p3
FROM t;