Parse data, single to multiple - sql

have a single column Varchar(2000).
Data looks like in a single column,
12:10:08: Dialing12:10:08: Connecting12:10:08: ABC: abc:9433769781$100.88.77.0:878712:10:08: ABCD: 000012:10:09: Agent Initializing12:10:25: On Call12:10:25: Assigned to operator12:10:25: Waiting for Supervisor12:10:30: Waiting for Manager12:11:30: Call Ended12:11:30: Call Not connected..
I want to parse it like,
12:10:08: Dialing
12:10:08: Connecting
12:10:08: ABC: abc:9433769782$100.88.77.0:8787
12:10:08: ABCD: 0000
12:10:25: Agent Initializing
12:10:18: On Call
12:10:25: Assigned to operator
12:10:30: Waiting for Supervisor
12:10:30: Waiting for Manager
12:11:30: Call Ended
12:11:30: Call Not connected
Any help. Searched the complete forum, but I am really unsure about this, particularly an absence of a specific identifier. Appreciate your help.
P/S- This is just an example of a single time,time is not constant.

Yuck. But, you can do this with a recursive CTE. Here is how:
with t as (
select '12:10:08: Dialing12:10:08: Connecting12:10:08: ABC: abc:9433769781$100.88.77.0:878712:10:08: ABCD: 000012:10:09: Agent Initializing12:10:25: On Call12:10:25: Assigned to operator12:10:25: Waiting for Supervisor12:10:30: Waiting for Manager12:11:30: Call Ended12:11:30: Call Not connected.. ' as col
),
cte as (
select left(t.col, 9 + patindex('%[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %', substring(t.col, 11, 1000))) as val,
substring(t.col, 10 + patindex('%[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %', substring(t.col, 11, 1000)), 1000) as rest
from t
where t.col like '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %'
union all
select (case when rest like '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %'
then left(rest, 9 + patindex('%[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %', substring(rest, 11, 1000)))
else rest
end) as val,
substring(rest, 10 + patindex('%[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %', substring(rest, 11, 1000)), 1000) as rest
from cte
where rest like '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]: %'
)
select val
from cte;
The SQL Fiddle is here.

Alternative;
DECLARE #string VARCHAR(1024) = '12:10:08: Dialing12:10:08: Connecting12:10:08: ABC: abc:9433769781$100.88.77.0:878712:10:08: ABCD: 000012:10:09: Agent Initializing12:10:25: On Call12:10:25: Assigned to operator12:10:25: Waiting for Supervisor12:10:30: Waiting for Manager12:11:30: Call Ended12:11:30: Call Not connected'
WITH T(last, pos) AS(
SELECT 0, 1
UNION ALL
SELECT pos, pos + PATINDEX('%[0-9][0-9]:[0-9][0-9]:[0-9][0-9]%', SUBSTRING(#string, pos + 1, LEN(#string)))
FROM T
WHERE pos != last
)
SELECT SUBSTRING(#string, last, CASE WHEN pos = last THEN len(#string) ELSE pos - last END)
FROM T
WHERE LAST > 0
For
(No column name)
12:10:08: Dialing
12:10:08: Connecting
12:10:08: ABC: abc:9433769781$100.88.77.0:8787
12:10:08: ABCD: 0000
12:10:09: Agent Initializing
12:10:25: On Call
12:10:25: Assigned to operator
12:10:25: Waiting for Supervisor
12:10:30: Waiting for Manager
12:11:30: Call Ended
12:11:30: Call Not connected

I know you are asking for an SQL solution but I am not sure that is possible without a while loop and extensive string manipulation which is quite inefficient.
If you are happy to bring the original varchar down to the BLL level, you can do it here using a regular expression. As I assume you want to do this in order to output to screen or log file then this should be possible.
For example:
Replace
/([0-9]{2}:[0-9]{2}:[0-9]{2}: ).*/gU
with
\n/1
Example:
http://regex101.com/r/eM4vD5/1

Related

In memory queries using SQL Server

I'm afraid that even though I am using CTE's in my query, that maybe, behind the scenes, a lot of disk caching is going on -- so it may as well not be using CTE's.
The whole point of using CTE's was that my original query code was way too slow, and would eventually get a transport level error and crash.
Well, it's still too slow. Maybe even slower. I don't know yet.
Is there a way to tell SQL Server to go ahead and be resource hog for my query?
I am only guessing, but I think it is using disk space to cache memory results. When I look at task manager memory utilization, I see SSMS at 161 MB. SSMS is where I am running the query from.
Here is my code - you don't have to read it in detail, but in brief, the source table contains about a million rows.
I need a solution, so alternative ideas are welcome...
WITH MetEdFliers AS
(
SELECT DISTINCT
[CustomerName1], [Mailing_Address], [Mailing_Address2], [Mailing_Zip]
FROM
[dbo].[_MetEd_Detail]
WHERE
RunId = (SELECT RunId FROM LastLoadRuns WHERE UtilityId = 9)
AND [Profitable] = 1 -- and not low income, should flag exist
),
MetEdLookUpFirst AS
(
-- same as [dbo].[VW_MetEd_Master_Profitable_ExcludeBadAddress]
SELECT
IIF (DET.IncalculableMailAddress = 1,
IIF (AA.Address1 IS NULL, 'Bad Address Undefined Fix -- Source Address Provided', 'Fixed Bad Source Address Via Lookup'), '') AS AddressStatus,
DET.ACCT_NO,
(CAST(DET.Monthly1 as Decimal) +
CAST(DET.Monthly2 as Decimal) +
CAST(DET.Monthly3 as Decimal) +
CAST(DET.Monthly4 as Decimal) +
CAST(DET.Monthly5 as Decimal) +
CAST(DET.Monthly6 as Decimal) +
CAST(DET.Monthly7 as Decimal) +
CAST(DET.Monthly8 as Decimal) +
CAST(DET.Monthly9 as Decimal) +
CAST(DET.Monthly10 as Decimal) +
CAST(DET.Monthly11 as Decimal) +
CAST(DET.Monthly12 as Decimal)) AS BilledKWHTotal,
DET.Polar, DET.CustomerName1,
REPLACE (IIF (DET.IncalculableMailAddress = 1,
IIF (AA.Address1 IS NULL, DET.Mailing_Address, AA.Address1), DET.Mailing_Address), ',', ';') AS Address1,
REPLACE (IIF (DET.IncalculableMailAddress = 1,
IIF (AA.Address2 IS NULL, DET.Mailing_Address2, AA.Address2), DET.Mailing_Address2), ',', ';') AS Address2,
REPLACE (IIF (DET.IncalculableMailAddress = 1,
IIF (AA.City IS NULL, DET.Mailing_City, AA.City), DET.Mailing_City), ',', ';') AS City,
IIF (DET.IncalculableMailAddress = 1,
IIF (AA.[State] IS NULL, DET.Mailing_State, AA.[State]), DET.Mailing_State) AS [State],
IIF (DET.IncalculableMailAddress = 1,
IIF (AA.Zip IS NULL, DET.Mailing_Zip, AA.Zip), DET.Mailing_Zip) AS ZIP,
IIF (DET.IncalculableMailAddress = 1, '', DET.Mailing_Zip4) AS ZIP4,
REPLACE (DET.Address, ',', ';') AS ServiceAddress,
REPLACE (DET.City, ',', ';') AS ServiceAddressCity,
DET.State ASs ServiceAddressState,
DET.Zip AS ServiceAddressZip,
DET.Zip4 AS ServiceAddressZip4,
DET.ProfitAnnualPotential AS [Potential Annual Profit]
FROM
_MetEd_DETAIL DET
LEFT JOIN
AccountAddress AA ON (DET.ACCT_NO = AA.ACCT_NO AND AA.UtilityId = 9)
WHERE
RunId = (SELECT RunId FROM LastLoadRuns WHERE UtilityId = 9)
AND DET.Profitable = 1 --AND det.CAP_CUSTOMER = 0
AND (DET.IncalculableMailAddress = 0 OR (AA.Address1 IS NOT NULL))
)
SELECT X.*
FROM MetEdFliers Fliers
OUTER APPLY
(SELECT TOP 1 *
FROM MetEdLookUpFirst LU
WHERE LU.CustomerName1 = Fliers.CustomerName1
AND LU.Address1 = Fliers.Mailing_Address
AND LU.Address2 = Fliers.Mailing_Address2
AND LU.Zip = Fliers.Mailing_Zip) X
It looks to be difficult.
I am going to handle it in my source program that generates input files for the sql server database ( i real the cvs into a table using import ).
To handle this problem, I am going to use a technology called dictionary, with key value pair, in c#.
I will be able to tell if the key had been added before, and if so, I replace the key value pair with the new key value pair and the annual profit potential field with the sum from both records....
Note: Prior method, I did not have sum (enhancement).

T-SQL to pull through everything between : and ; only

I am looking to pull through everything after an : and before a ;.
For example my current code is:
select Left('{Script.Testdata}', CHARINDEX('; ',('{Script.Testdata}'))-1)
This currently pulls " Leon: My Job" through data from: Leon: My Job; New job
I am looking for this to pull through only My Job instead of Leon: My Job. So everything from the : and between the ; but everything between ; and ; not to show.
Here is one method:
select left(stuff(col, 1, charindex(':', col), ''),
charindex(';', stuff(col, 1, charindex(':', col), '')) - 1
)
Of course, this gets more complicated if the string may not have : or ;.
declare #var varchar(30)
set #var=' Leon: My Job; New jobs;;;'
select Substring(substring (#var,charindex(':',#var)+1,Len(#var)),0,
CHARINDEX('; ',substring (#var,charindex(':',#var)+1,Len(#var))))

Natural sort with SQL Server

I want to convert the order of the values with column name PTNT_VST_CSNO from the following :
VMIP1
VMIP10
VMIP11
VMIP2
VMIP20
VMIP21
VMIP3
VMIP31
VMIP32
VMIP5
VMIP6
VMIP7
VMIP8
VMIP9
VMOP10
VMOP11
VMOP12
VMOP3
VMOP30
VMOP31
VMOP32
VMOP4
VMOP40
VMOP41
VMOP42
VMOP43
VMOP7
VMOP70
VMOP71
VMOP8
VMOP9
to:
VMIP1
VMIP2
VMIP3
VMIP5
VMIP6
VMIP7
VMIP8
VMIP9
VMIP10
VMIP11
VMIP20
VMIP21
VMIP31
VMIP32
VMOP3
VMOP4
VMOP7
VMOP8
VMOP9
VMOP10
VMOP11
VMOP12
VMOP30
VMOP31
VMOP32
VMOP40
VMOP41
VMOP42
VMOP43
VMOP70
VMOP71
I want to sort the numeric part of 'vmip' first then that of 'vmop'.. I tried a lot but failed every time. kindly help me guys to sort out the sorting problem... thank you in advance
Not the fastest thing in the world, but it should get the job done:
ORDER BY CASE WHEN PTNT_VST_CSNO LIKE 'vmi%' THEN 0 ELSE 1 END
,CAST(replace(replace(PTNT_VST_CSNO, 'vmip', ''), 'vmop', '') as int)
After great trial, I succeeded to solve it with the following way..
SELECT ptnt_vst_csno
FROM table_name
ORDER BY Substring(ptnt_vst_csno, 1, Charindex('P', ptnt_vst_csno)),
CONVERT(INT, Substring(Substring(ptnt_vst_csno,
Charindex('P', ptnt_vst_csno),
Len(
ptnt_vst_csno)), 2, Len(
ptnt_vst_csno)))
the easiest way to accomplish this would be to change your numering to 3 digits.
i.e. 1 would become 001, 2 would become 002, 10 would become 010, and so on...
this would then allow you to order the data correctly.
you might want to do something like this:
SELECT
PTNT_VST_CSNO,
'VMIP' + CASE LEN(REPLACE(PTNT_VST_CSNO, 'VMIP', ''))
WHEN 1 THEN '00' + REPLACE(PTNT_VST_CSNO, 'VMIP', '')
WHEN 2 THEN '0' + REPLACE(PTNT_VST_CSNO, 'VMIP', '')
ELSE REPLACE(PTNT_VST_CSNO, 'VMIP', '')
END
FROM
TableName
WHERE
LEFT(PTNT_VST_CSNO, 4) = 'VMIP'
ORDER BY
2

How to search string to find data after end of pattern of characters (SQL DB2)

I need to find the next single event that appears after the last occurrence of the following pattern of events "5065|5373|5373". My problem is that the pattern can be in the string 1 to n times. Here's an example of the some data that I have to search through.
The events in BOLD are what i would be looking for.
5065|5373|5373|5065|5373|5373|5065|5373|5373|5509|5329|5321
5065|5373|5373|5065|5373|5373|5509|5270|5373|5373|5373|5080|5081|5013|5040|5295|5321
5065|5373|5373|5295|5323|5321
Any help would be greatly appreciated!
If you can't create a new stored procedure or UDF, here's a recursive query that'll do it for you:
WITH Recurs(id, index, token, source) as (
SELECT id, LOCATE('5065|5373|5373|', M.PATH_2), '', M.PATH_2
FROM M
UNION ALL
SELECT id, LOCATE('5065|5373|5373|', source, index + 15),
SUBSTR(source, index + 15, 4), source
FROM Recurs
WHERE index > 0)
SELECT *
FROM Recurs
WHERE index = 0
Which yields the expected:
ID INDEX TOKEN SOURCE
3 0 5295 5065|5373|5373|5295|5323|5321
2 0 5509 5065|5373|5373|5065|5373|5373|5509|5270|5373|5373|5373|5080|5081|5013|5040|5295|5321
1 0 5509 5065|5373|5373|5065|5373|5373|5065|5373|5373|5509|5329|5321
One fairly straightforward way to do this is with a recursive common table expression (CTE):
CREATE FUNCTION localutil.locatelastmatch(
searchparm VARCHAR(4000), inputparm VARCHAR(4000)
)
RETURNS SMALLINT
LANGUAGE SQL
RETURN
WITH rcurs(counter, output ) AS (
VALUES (0,0)
UNION ALL
SELECT counter+1, LOCATE(searchparm,inputparm,counter+1)
FROM rcurs
WHERE counter < LENGTH(inputparm) AND counter < 32767
)
SELECT MAX(output) FROM rcurs
;
It may not be the cheapest way to find the last matching occurrence, but it's at least a contender for it. By burying the complexity into a scalar user-defined function (UDF), you won't have to introduce the SQL recursion into every query that needs to search for the last instance of a pattern.
Here's how it works against your sample strings:
WITH originput(val) as (VALUES
('5065|5373|5373|5065|5373|5373|5065|5373|5373|5509|5329|5321'),
('5065|5373|5373|5065|5373|5373|5509|5270|5373|5373|5373|5080|5081|5013|5040|5295|5321'),
('5065|5373|5373|5295|5323|5321')
)
SELECT LENGTH(val) AS inputlength,
localutil.locatelastmatch( '5065|5373|5373|', val ) AS finaloffset,
SUBSTR(val, localutil.locatelastmatch( '5065|5373|5373|', val )
+ LENGTH( '5065|5373|5373|' ), 4) AS nextitem
FROM originput
;
INPUTLENGTH FINALOFFSET NEXTITEM
----------- ----------- --------
59 31 5509
84 16 5509
29 1 5295

Return all results of substring with in string

I have some odd data in a vendor database but need to be able to extract multiple different parameters from one field in the db.
So from this example i would like to pull out all items that fall between (" % ")
Between quotes is a string, disregard that it looks like code:
"Func_GetParameterLatestValue("IBW Patient Height RT Assess") kHeight =Func_GetParameterLatestValue("Height For IBW Vent Misc") If (kSex) = "" Then
Return_Value =NULL Else If kHeight > 0 Then If kSex=1 Then Return_Value= Round(((kHeight - 152.4)*.91)+50,0) Else
Return_Value= Round(((kHeight - 152.4)*.91)+45.5,0) End IF Else Return_Value = NULL End IF End IF ' Return_Value = kHeight '("IBW Patient Height RT Assess")"
so the return values would be:
IBW Patient Height RT Assess,
Height For IBW Vent Misc,
IBW Patient Height RT Assess
Im open to any suggestions to try and make this work. Ideally i would like to be able to slam the results in a subquery as well to make sure that they exist on another table.
This query currently returns the first instance
select vbs.Name,
SUBSTRING(sd.FormulaDetails,
CHARINDEX('("', sd.FormulaDetails)+2,(CHARINDEX('")',sd.FormulaDetails) - CHARINDEX('("', sd.FormulaDetails))-2)
from StatementDefinitions sd, MvVBScript vbs
where sd.ScriptID = vbs.ID
You can do this recursively with a WITH statement. Here's a shot at it. Change varchar(max) to whatever the data type of your FormulaDetails column is. In case you want it, this query returns the ScriptID and numbers the position of the chunk it finds (so 'Height For IBW Vent Misc' would be occurrence 2)
with Chunks(id,occurrence,position,token,remainder) as (
select
ScriptID,
cast(0 as int),
charindex(#token,FormulaDetails),
cast('' as varchar(max)),
substring(c,charindex(#token,FormulaDetails)+1,len(FormulaDetails))
from StatementDefinitions
where FormulaDetails like '%'+#token+'%'
union all
select
id,
occurrence+1,
charindex(#token,remainder)+position,
cast(substring(remainder,1,charindex(#token,remainder)-1) as varchar(max)),
substring(remainder,charindex(#token,remainder)+1,len(remainder))
from Chunks
where remainder like '%'+#token+'%'
)
select id, occurrence, token from Chunks
where occurrence > 0
order by id;