I have this query i'm trying to get working that can extract decimal numbers from a string so they are their own columns. The goal is to then compare the values are order them, so they will also need to be converted to decimal ( Getting the numbers out of the string is main problem though)
The example i'm using is with the string "OrdRevenuePay 3200.00 -> 2836.07, OrdRate 3200.00 -> 2836.07"
I need to have each of the numbers in that string as their own column. What i have so far is able to select the first value, but the second value is returning other parts as well. This is the query i've been working with so far:
DECLARE #str VARCHAR(128)
SET #str = 'OrdRevenuePay 3200.00 -> 2836.07, OrdRate 3200.00 -> 2836.07'
SELECT SUBSTRING(#str,CHARINDEX(' ',#str)+1,CHARINDEX('->',#str)-CHARINDEX(' ',#str)-1) as col1
, SUBSTRING(#str,CHARINDEX('->',#str,1)+2,LEN(#str)-CHARINDEX(', OrdRate',#str,1)-1) as col2
DECLARE #str VARCHAR(128)
SET #str = 'OrdRevenuePay 3200.00 -> 2836.07, OrdRate 3200.00 -> 2836.07'
; WITH ReplaceX
AS (
SELECT REPLACE(REPLACE(LEFT(#str,CHARINDEX(',',#str)-1),' -> ','`'),' ','~') + '|' +
REPLACE(REPLACE(RIGHT(#str,LEN(#str) - CHARINDEX(',',#str) - 1),' -> ','}'),' ','{') + '^' AS NewString
)
SELECT SUBSTRING(NewString,CHARINDEX('~',NewString)+1,CHARINDEX('`',NewString)-CHARINDEX('~',NewString)-1),
SUBSTRING(NewString,CHARINDEX('`',NewString)+1,CHARINDEX('|',NewString)-CHARINDEX('`',NewString)-1),
SUBSTRING(NewString,CHARINDEX('{',NewString)+1,CHARINDEX('}',NewString)-CHARINDEX('{',NewString)-1),
SUBSTRING(NewString,CHARINDEX('}',NewString)+1,CHARINDEX('^',NewString)-CHARINDEX('}',NewString)-1)
FROM ReplaceX
Related
I have a string that I need to seperate into values seperated by commas. I have achieved this part with the below REPLACE statement:
declare #mc varchar(200)
declare #mc1 varchar(200)
select #mc = 'FRED&#g4;g;MARY&#g4;g;BILL&#g4;g;TIMOTHY&#g4;g;JOHNATHAN'
select #mc1 = REPLACE(#mc, '&#g4;g;',', ')
The replace returns a string 'FRED, MARY, BILL, TIMOTHY, JOHNATHAN'
I then want to have another variable that will return the first 3 characters of each value before the commas, so the above string would be returned as:
'FRE, MAR, TIM, JOH'
Anyone know how I can achieve this?
Also happy for this to be done directly to the original #mc variable
ON SQL Server 2017+ you can make use of openJson to split the string into manageble segments and then string_agg to assemble the desired result:
declare #mc varchar(100)='FRED&#g4;g;MARY&#g4;g;BILL&#g4;g;TIMOTHY&#g4;g;JOHNATHAN'
select String_Agg(v, ', ')
from (select #mc)x(s)
cross apply (
select Left(j.[value],3) v, Convert(tinyint,j.[key]) Seq
from OpenJson(Concat('["',replace(s,';', '","'),'"]')) j
where Convert(tinyint,j.[key]) % 2 = 0
)j;
Demo Fiddle
I find in my sql database string whit weird whitespace which cannot be replace like REPLACE(string, ' ', '') RTRIM and cant it even find with string = '% %'. This space is even transfered to new table when using SELECT string INTO
If i select this string in managment studio and copy that is seems is normal space and when everything is works but cant do nothing directly from database. What else can i do? Its some kind of error or can i try some special character for this?
First, you must identify the character.
You can do that by using a tally table (or a cte) and the Unicode function:
The following script will return a table with two columns: one contains a char and the other it's unicode value:
DECLARE #Str nvarchar(100) = N'This is a string containing 1 number and some words.';
with Tally(n) as
(
SELECT TOP(LEN(#str)) ROW_NUMBER() OVER(ORDER BY ##SPID)
FROM sys.objects a
--CROSS JOIN sys.objects b -- (unremark if there are not enough rows in the tally cte)
)
SELECT SUBSTRING(#str, n, 1) As TheChar,
UNICODE(SUBSTRING(#str, n, 1)) As TheCode
FROM Tally
WHERE n <= LEN(#str)
You can also add a condition to the where clause to only include "special" chars:
AND SUBSTRING(#str, n, 1) NOT LIKE '[a-zA-Z0-9]'
Then you can replace it using it's unicode value using nchar (I've used 32 in this example since it's unicode "regular" space:
SELECT REPLACE(#str, NCHAR(32), '|')
Result:
This|is|a|string|containing|1|number|and|some|words.
For a single value it works fine when I cast it to text:
WHERE product_id::text in (inputProduct_ids)
But I have problems if there is more than one value:
CREATE FUNCTION ourFunction(text) {
inputProduct_ids text := $1;
SELECT STRING_AGG(product_id::TEXT, ',' ORDER BY product_id)
INTO product_ids
FROM product_table
WHERE product_id in ('||inputProduct_ids||');
}
select ourFunction('573, 574 , 575 , 576 , 579 , 580 ,581 , 584');
If you really have to pass the argument as a string, you can cast it to an array of integer in the query:
SELECT string_agg(product_id::TEXT, ',' ORDER BY product_id)
INTO product_ids
FROM product_table
WHERE product_id =ANY (CAST('{' || $1 || '}' AS integer[]));
The =ANY operator can be used with arrays and does the same as IN (in fact the optimizer translates IN into =ANY internally).
As a_horse_with_no_name pointed out, you can also use string_to_array instead of a type cast:
WHERE CAST(product_id AS text) =ANY (string_to_array($1, ','))
I want to implement a stored procedure that extract letters from a varchar in firebird.
Example :
v_accountno' is of type varchar(50) and has the following values
accountno 1 - 000023208821
accountno 2 - 390026826850868140H
accountno 3 - 0700765001003267KAH
I want to extract the letters from v_accountno and output it in o_letter.
In my example: o_letter will store H for accountno 2 and KAH for accountno 3.
I tried the following stored procedure, which obviously won't work for accountno 3. (Please help).
CREATE OR ALTER PROCEDURE SP_EXTRACT_LETTER
returns (
o_letter varchar(50))
as
declare variable v_accountno varchar(50);
begin
v_accountno = '390026826850868140H';
if (not (:v_accountno similar to '[[:DIGIT:]]*')) then
begin
-- My SP won't work in for accountno 3 '0700765001003267KAH'
v_accountno = longsubstr(v_accountno, strlen(v_accountno), strlen(v_accountno));
o_letter = v_accountno;
end
suspend;
end
One solution would be to replace every digits with empty string like:
o_letter = REPLACE(v_accountno, '0', '')
o_letter = REPLACE(o_letter, '1', '')
o_letter = REPLACE(o_letter, '2', '')
...
Since Firebird 3, you can use substring for this, using its regex facility (using the similar clause):
substring(v_accountno similar '[[:digit:]]*#"[[:alpha:]]*#"' escape '#')
See also this dbfiddle.
I am working on migrating data from one database to another for a hospital. In the old database, the doctor's specialty IDs are all in one column (swvar_specialties), each separated by commas. In the new database, each specialty ID will have it's own column (example: Specialty1_PrimaryID, Specialty2_PrimaryID, Specialty3_PrimaryID, etc). I am trying to export the data out of the old database and separate these into these separate columns. I know I can use indexof and substring to do this - I just need help with the syntax.
So this query:
Select swvar_specialties as Specialty1_PrimaryID
From PhysDirectory
might return results similar to 39,52,16. I need this query to display Specialty1_PrimaryID = 39, Specialty2_PrimaryID = 52, and Specialty3_PrimaryID = 16 in the results. Below is my query so far. I will eventually have a join to pull the specialty names from the specialties table. I just need to get this worked out first.
Select pd.ref as PrimaryID, pd.swvar_name_first as FirstName, pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName, pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as NameSuffix,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation, 'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender, pd.swvar_specialties as Specialty1_PrimaryID, pd.swvar_languages as Language1_Name
From PhysDirectory as pd
The article Split function equivalent in T-SQL? provides some details on how to use a split function to split a comma-delimited string.
By modifying the table-valued function in presented in this article to provide an identity column we can target a specific row such as Specialty1_PrimaryID:
/*
Splits string into parts delimitered with specified character.
*/
CREATE FUNCTION [dbo].[SDF_SplitString]
(
#sString nvarchar(2048),
#cDelimiter nchar(1)
)
RETURNS #tParts TABLE (id bigint IDENTITY, part nvarchar(2048) )
AS
BEGIN
if #sString is null return
declare #iStart int,
#iPos int
if substring( #sString, 1, 1 ) = #cDelimiter
begin
set #iStart = 2
insert into #tParts
values( null )
end
else
set #iStart = 1
while 1=1
begin
set #iPos = charindex( #cDelimiter, #sString, #iStart )
if #iPos = 0
set #iPos = len( #sString )+1
if #iPos - #iStart > 0
insert into #tParts
values ( substring( #sString, #iStart, #iPos-#iStart ))
else
insert into #tParts
values( null )
set #iStart = #iPos+1
if #iStart > len( #sString )
break
end
RETURN
END
Your query can the utilise this split function as follows:
Select
pd.ref as PrimaryID,
pd.swvar_name_first as FirstName,
pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName,
pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as LastName,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation,
'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=1) as Specialty1_PrimaryID,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=2) as Specialty2_PrimaryID,
pd.swvar_languages as Language1_Name
From PhysDirectory as pd