LOCATE_IN_STRING Function in Db2 - db2

Using LOCATE_IN_STRING function in Db2 , I want to separate Field 2 & Field 3 from below string.
RTN1319 5.7.18 INSUFFICIENT FUNDS
Field 1 : Chk Number Field
Field 2 : Tr Date Field
Field 3 : Reason
I want to pull only TR Date & Reason
Select TRIM(SUBSTR(TRIM('RTNCK1319 5.7.19 INSUFFICIENT FUNDS'),LOCATE_IN_STRING(TRIM('RTNCK1319 5.7.19 INSUFFICIENT FUNDS'),' ',+1))) from SYSIBM.SYSDUMMY1 ;
Select TRIM(SUBSTR(TRIM('RTNCK1319 5.7.19 INSUFFICIENT FUNDS'),LOCATE_IN_STRING(TRIM('RTNCK1319 5.7.19 INSUFFICIENT FUNDS'),' ',+1))) from SYSIBM.SYSDUMMY1 ;

For all Db2 for LUW versions:
with t (s) as (values
'RTNCK1319 5.7.19 INSUFFICIENT FUNDS'
)
select
xmlcast(xmlquery('fn:tokenize($s, " +")[2]' passing ltrim(t.s) as "s") as varchar(10))
, xmlcast(xmlquery('fn:replace($s, "^ *[^ ]+ +[^ ]+ +", "")' passing t.s as "s") as varchar(100))
from t;
Without regexp (1-st two intermediate spaces must be single):
with t (s) as (values
'RTNCK1319 5.7.19 INSUFFICIENT FUNDS'
)
select
substr(s, s1pos+1, s2pos-s1pos) s1
, substr(s, s2pos+1) s2
from
(
select
ltrim(s) s
, locate_in_string(ltrim(s), ' ', 1, 1) s1pos
, locate_in_string(ltrim(s), ' ', 1, 2) s2pos
from t
);

Related

Postgres make spaces with ''::text statement

Does anyone know why Postgresql 9.3.17 do this with concat() function ?
If I do :
SELECT concat(tab.a::text, ' '::text, tab.b::text) AS field FROM schem.tab
I'll have "a b" with 3 spaces (one in the ' ' and two added by Postgres)
If I do:
SELECT concat(concat(tab.a::text, ' '::text), tab.b::text) AS field FROM schem.tab
I'll have "a b" with my only space

query throwing error in web report writer

I have a query/view that is created to be used in a report. When I run in the SMS and in SSRS it run fine. But when I connect the view to the tool that generates our reports it throws the following error. Incorrect syntax near '.8'. When I contact the support for this product they say it has to do with how we calculate the 8thgradyear . I have placed the code below. Any suggestions.
SELECT
dbo.studemo.suniq,
dbo.studemo.ident,
dbo.studemo.lastname,
dbo.studemo.firstname,
dbo.studemo.emailaddr AS stuemail,
dbo.studemo.birthdate,
dbo.track.schoolc,
dbo.school.schname,
dbo.stustat.graden,
dbo.stustat.edate,
dbo.zstustat.descript AS status,
RTRIM(dbo.facdemo.lastname) + ' ' + dbo.facdemo.firstname AS advisor,
dbo.track.schyear,
SUM(8) - dbo.stustat.graden + dbo.track.schyear AS [8thgradyear],
sf.Email, LOWER(sf.Username) AS [user],
LOWER(RIGHT(SUM(8) - dbo.stustat.graden + dbo.track.schyear, 2) + LEFT(dbo.studemo.firstname, 1) + REPLACE(REPLACE(REPLACE(dbo.studemo.lastname, '-', ''), ' ', ''), '''', '') + RIGHT(dbo.studemo.ident, 3)) AS newuser,
CONVERT(varchar(8), dbo.studemo.birthdate,1) AS password,
'STUDENTS' + '/' + (CASE WHEN track.schoolc IN ('19', '43', '17', '23') THEN 'Middle' ELSE 'Elementary' END) + '/' + dbo.school.schname AS neworg,
sf.OU, sf.LastLoginTime
FROM dbo.studemo INNER JOIN
dbo.stustat ON dbo.studemo.suniq = dbo.stustat.suniq INNER JOIN
dbo.track ON dbo.stustat.trkuniq = dbo.track.trkuniq INNER JOIN
dbo.zstustat ON dbo.stustat.stustatc = dbo.zstustat.stustatc INNER JOIN
dbo.facdemo ON dbo.stustat.funiq = dbo.facdemo.funiq LEFT OUTER JOIN
dbo.vw_google_OU AS sf ON sf.Firstname = dbo.studemo.firstname AND sf.Lastname = dbo.studemo.lastname INNER JOIN
dbo.school ON dbo.school.schoolc = dbo.track.schoolc
WHERE (dbo.stustat.stustatc IN
(SELECT stustatc
FROM dbo.zstustat AS zstustat_1
WHERE (snstatus IN ('A', 'M', 'P')))) AND (dbo.stustat.xdate IS NULL OR
dbo.stustat.xdate < dbo.stustat.edate) AND (dbo.track.schoolc NOT IN ('P34', 'P24', '802', '801'))
GROUP BY dbo.studemo.suniq, dbo.studemo.ident, dbo.studemo.lastname, dbo.studemo.firstname, dbo.studemo.birthdate, RIGHT(dbo.studemo.ident, 3), dbo.track.schoolc,
dbo.stustat.graden, dbo.zstustat.descript, RTRIM(dbo.facdemo.lastname) + ' ' + dbo.facdemo.firstname, dbo.stustat.edate, dbo.studemo.gradyear, dbo.track.schyear,
sf.Email, CONVERT(varchar(8), dbo.studemo.birthdate, 1), sf.Username, dbo.school.schname, sf.OU, dbo.studemo.emailaddr, sf.LastLoginTime
SUM function was introduced in SQL Server 2008 and your tool must be using and older version of SQL Server.

PGSQL - Joining two tables on complicated condition

I got stuck during database migration on PostgreSQL and need your help.
I have two tables that I need to join: drzewa_mateczne.migracja (data I need to migrate) and ibl_as.t_adres_lesny (dictionary I need to join with migracja).
I need to join them on replace(drzewa_mateczne.migracja.adresy_lesne, ' ', '') = replace(ibl_as.t_adres_lesny.adres, ' ', ''). However my data is not very regular, so I want to join it on first good match with the dictionary.
I've created the following query:
select
count(*)
from
drzewa_mateczne.migracja a
where
length(a.adresy_lesne) > 0
and replace(a.adresy_lesne, ' ', '') = (select substr(replace(al.adres, ' ', ''), 1, length(replace(a.adresy_lesne, ' ', ''))) from ibl_as.t_adres_lesny al limit 1)
The query doesn't return any rows.
It does successfully join empty rows if ran without
length(a.adresy_lesne) > 0
The two following queries return rows (as expected):
select replace(adres, ' ', '')
from ibl_as.t_adres_lesny
where substr(replace(adres, ' ', ''), 1, 16) = '16-15-1-13-180-c'
limit 1
select replace(adresy_lesne, ' ', ''), length(replace(adresy_lesne, ' ', ''))
from drzewa_mateczne.migracja
where replace(adresy_lesne, ' ', '') = '16-15-1-13-180-c'
I'm suspecting that there might be a problem in sub-query inside the 'where' clause in my query. If you guys could help me resolve this issue, or at least point me in the right direction, I'd be very greatful.
Thanks in advance,
Jan
You can largely simplify to:
SELECT count(*)
FROM drzewa_mateczne.migracja a
WHERE a.adresy_lesne <> ''
AND EXISTS (
SELECT 1 FROM ibl_as.t_adres_lesny al
WHERE replace(al.adres, ' ', '')
LIKE (replace(a.adresy_lesne, ' ', '') || '%')
)
a.adresy_lesne <> '' does the same as length(a.adresy_lesne) > 0, just faster.
Replace the correlated subquery with an EXISTS semi-join (to get only one match per row).
Replace the complex string construction with a simple LIKE expression.
More information on pattern matching and index support in these related answers:
PostgreSQL LIKE query performance variations
Difference between LIKE and ~ in Postgres
speeding up wildcard text lookups
What you're basically telling the database to do is to get you the count of rows from drzewa_mateczne.migracja that have a non-empty adresy_lesne field that is a prefix of the adres field of a semi-random ibl_as.t_adres_lesny row...
Lose the "limit 1" in the subquery and substitute the "=" with "in" and see if that is what you wanted...

Using IndexOf and/Or Substring to parse data into separate columns

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

Extract the first word of a string in a SQL Server query

What's the best way to extract the first word of a string in sql server query?
SELECT CASE CHARINDEX(' ', #Foo, 1)
WHEN 0 THEN #Foo -- empty or single word
ELSE SUBSTRING(#Foo, 1, CHARINDEX(' ', #Foo, 1) - 1) -- multi-word
END
You could perhaps use this in a UDF:
CREATE FUNCTION [dbo].[FirstWord] (#value varchar(max))
RETURNS varchar(max)
AS
BEGIN
RETURN CASE CHARINDEX(' ', #value, 1)
WHEN 0 THEN #value
ELSE SUBSTRING(#value, 1, CHARINDEX(' ', #value, 1) - 1) END
END
GO -- test:
SELECT dbo.FirstWord(NULL)
SELECT dbo.FirstWord('')
SELECT dbo.FirstWord('abc')
SELECT dbo.FirstWord('abc def')
SELECT dbo.FirstWord('abc def ghi')
I wanted to do something like this without making a separate function, and came up with this simple one-line approach:
DECLARE #test NVARCHAR(255)
SET #test = 'First Second'
SELECT SUBSTRING(#test,1,(CHARINDEX(' ',#test + ' ')-1))
This would return the result "First"
It's short, just not as robust, as it assumes your string doesn't start with a space. It will handle one-word inputs, multi-word inputs, and empty string inputs.
Enhancement of Ben Brandt's answer to compensate even if the string starts with space by applying LTRIM(). Tried to edit his answer but rejected, so I am now posting it here separately.
DECLARE #test NVARCHAR(255)
SET #test = 'First Second'
SELECT SUBSTRING(LTRIM(#test),1,(CHARINDEX(' ',LTRIM(#test) + ' ')-1))
Adding the following before the RETURN statement would solve for the cases where a leading space was included in the field:
SET #Value = LTRIM(RTRIM(#Value))
Marc's answer got me most of the way to what I needed, but I had to go with patIndex rather than charIndex because sometimes characters other than spaces mark the ends of my data's words. Here I'm using '%[ /-]%' to look for space, slash, or dash.
Select race_id, race_description
, Case patIndex ('%[ /-]%', LTrim (race_description))
When 0 Then LTrim (race_description)
Else substring (LTrim (race_description), 1, patIndex ('%[ /-]%', LTrim (race_description)) - 1)
End race_abbreviation
from tbl_races
Results...
race_id race_description race_abbreviation
------- ------------------------- -----------------
1 White White
2 Black or African American Black
3 Hispanic/Latino Hispanic
Caveat: this is for a small data set (US federal race reporting categories); I don't know what would happen to performance when scaled up to huge numbers.
DECLARE #string NVARCHAR(50)
SET #string = 'CUT STRING'
SELECT LEFT(#string,(PATINDEX('% %',#string)))
Extract the first word from the indicated field:
SELECT SUBSTRING(field1, 1, CHARINDEX(' ', field1)) FROM table1;
Extract the second and successive words from the indicated field:
SELECT SUBSTRING(field1, CHARINDEX(' ', field1)+1, LEN (field1)-CHARINDEX(' ', field1)) FROM table1;
A slight tweak to the function returns the next word from a start point in the entry
CREATE FUNCTION [dbo].[GetWord]
(
#value varchar(max)
, #startLocation int
)
RETURNS varchar(max)
AS
BEGIN
SET #value = LTRIM(RTRIM(#Value))
SELECT #startLocation =
CASE
WHEN #startLocation > Len(#value) THEN LEN(#value)
ELSE #startLocation
END
SELECT #value =
CASE
WHEN #startLocation > 1
THEN LTRIM(RTRIM(RIGHT(#value, LEN(#value) - #startLocation)))
ELSE #value
END
RETURN CASE CHARINDEX(' ', #value, 1)
WHEN 0 THEN #value
ELSE SUBSTRING(#value, 1, CHARINDEX(' ', #value, 1) - 1)
END
END
GO
SELECT dbo.GetWord(NULL, 1)
SELECT dbo.GetWord('', 1)
SELECT dbo.GetWord('abc', 1)
SELECT dbo.GetWord('abc def', 4)
SELECT dbo.GetWord('abc def ghi', 20)
Try This:
Select race_id, race_description
, Case patIndex ('%[ /-]%', LTrim (race_description))
When 0 Then LTrim (race_description)
Else substring (LTrim (race_description), 1, patIndex ('%[ /-]%', LTrim (race_description)) - 1)
End race_abbreviation
from tbl_races