Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 02:57:34
|
We have GPS devices which send data in many different formats . The formats of the packets and the length of the data packet varies. The delimiter string also is different ( could be , or pipe)Examples :357464031469825,183615.00,1256.3340,0,0^|1|1|1259.43332|07735.37427|35202402773555 These strings are stored in a db table( rawtable) with the timestamp and the table can have 15-20 million records.The strings must be parsed and packed,but the way in which they appear in the raw data packet differs . So, we need to parse depending on format of packet. Raw table can contains about 15-20 million records . Keeping performance in mind, how can I parse these strings depending on varied format in a sql server stored procedureEg: I need to get an output like For this string 357464031469825,183615.00,1256.3340,0,0output must be @UnitNo = 357464031469825,@Lat = 183615.00@Lon = 1256.3340,@IO1 = 0@IO2 = 0;For this string ^|1|1|1259.43332|07735.37427|35202402773555 output must be@UnitNo=35202402773555 @lat=1259.43332@lon=07735.37427@IO1=1@IO2=1As you can see the position in which they appear in the two strings are different. How can I parse it and populatethe variables correctly using sql server store procedure. Since the raw data table has many records , I need a procedure which is fast. Many thanks in advance |
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 03:08:51
|
use fnParseString from http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=76033select UnitNo = case when gps_data like '^%' then dbo.fnParseString( 1, '|', gps_data) else dbo.fnParseString(-1, ',', gps_data) end, lat = case when gps_data like '^%' then dbo.fnParseString(-4, '|', gps_data) else dbo.fnParseString(-2, ',', gps_data) end, . . . KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 03:23:24
|
fnParseString returned errorMsg 8116, Level 16, State 1, Procedure fnParseString, Line 16Argument data type text is invalid for argument 1 of reverse function. |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 03:28:00
|
Also,depending upon the device the position of unitno in the string can vary. We have about 50 devices right now( could increase) and also the number of substrings can be upto 42( unitno, lat,lan is just an example) . So I will need a general procedure which will be able to parse based on a format. I hope I am able to clearly state what I am looking for. |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 03:28:08
|
change to varchar(max) if you are using SQL 2005/2008 KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 04:59:01
|
Thanks . My worry is the no of devices is more and also the delimiter separated substrings will be 42. So is it possible to map position to substring for a particular device. ANy more ideas will really help |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 05:07:29
|
42 what is 42 ?if you have a device type, then you can based on the device type to decide what decoding method to use KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 05:24:10
|
Example :String A can be ^0609|8|2829.49673|07704.82322|13.627|130.59|140312075012|2|0|A|1|0|0|0|3.015600|12.230000|2748.26|76373.00|352024027728165|1212|......So the number of substrings in string A can be upto 42. And there are 50 devices ( so 50 formats where position of the substrings will differ ) |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 05:37:39
|
[code]^0609|8|2829.49673|07704.82322|13.627|130.59|140312075012|2|0|A|1|0|0|0|3.015600|12.230000|2748.26|76373.00|352024027728165|1212|......[/code]it will be always 5 value per device ? Can you help to identify which value are belong to a set ? KH[spoiler]Time is always against us[/spoiler] |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 05:56:23
|
[code]select gps_data, no_of_sets = case when gps_data like '^%' then (len(gps_data) - len(replace(gps_data, '|', ''))) / 5 else (len(gps_data) - len(replace(gps_data, ',', '')) + 1) / 5 end, UnitNo = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 6), '|', gps_data) else dbo.fnParseString(-((num * 5) + 1), ',', gps_data) end, lat = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 4), '|', gps_data) else dbo.fnParseString(-((num * 5) + 2), ',', gps_data) end, lon = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 5), '|', gps_data) else dbo.fnParseString(-((num * 5) + 3), ',', gps_data) end, IO1 = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 3), '|', gps_data) else dbo.fnParseString(-((num * 5) + 4), ',', gps_data) end, IO2 = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 2), '|', gps_data) else dbo.fnParseString(-((num * 5) + 5), ',', gps_data) endfrom yourtable t inner join numbers n on n.num >= 0 and n.num < case when gps_data like '^%' then (len(gps_data) - len(replace(gps_data, '|', ''))) / 5 else (len(gps_data) - len(replace(gps_data, ',', '')) + 1) / 5 end[/code]numbers is a number table contain value 0, 1, 2, 3 etc[code]create table numbers (num int) declare @num intselect @num = 0while @num < 10000begin insert into numbers (num) select @num select @num = @num + 1end[/code] KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 06:06:56
|
Sorry for any confusion .I will explain my requirement again.I have a rawdatatable which has abt 20 million recordsThe table has one varchar column sample record is ^0609|11|2835.11552|07720.85664|6.6891|50.012|210312054133|2|3|A|1|0|0|0|0.632900|12.788500|67825.45|66883.00|352024027735038|1213.1|455|2323|8987|343|5454|0|0|0|0|0|0|1|11|11|1|33|0|0|0|0|0Here we want to parse this record and assign values eg:@unitid=210312054133 (position 7)@cmdid=0609@io1=11@lat=1212... and so on ( all the 42 substrings of this must be assigned)This is for 1 device.I can have another device which will send rawdata where each record will have 42 substrings as part of the long data packet/ But the position will be different.Eg:String B from another device 357464031469825,1212,GPRMC,183615.00,A,1256.3340,N,08011.1400,E,0.0,0.0,190312,,,A*51,0,5014,0,0,0,0,0,0,0,0,0,0,0,12,1212,0,0,0,0,0,0,0,0,0,1,1212Note that the delimter is , in this case and @unitid=357464031469825 ( position 1)@cmdid=1212 ( psoition 2) So I will need all 42 substrings of every data packet packed respectively into same variables like (unitid,cmdid,io1,io2....... etc) , only the position they appear is different There can be atleast 50 format ( position diff) for now. I want a general procedure which will handle these formats and also be fast as the no of records in the table is large.Hope I am clear now. Thanks in advance |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 06:12:54
|
it will be easier if you can accept the result in rows rather than column as what i have shown in my last post. Just use the same technique and adjust the position accordingly KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-28 : 06:19:54
|
It will be 42 values per device . 42 values in different positions dependent on device |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-28 : 07:50:06
|
quote: Originally posted by abk It will be 42 values per device . 42 values in different positions dependent on device
see the query Posted - 03/28/2012 : 05:56:23it should be able to do the job KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-29 : 05:01:35
|
Many thanks for the query. I need help in understanding this query .I have a data packet string in this format for a new device in hex format.( delimter is space)They are in hex and I need to convert to decimalFC03 00140700 00007D04 0002E702 0001624F 00C02A9D 049C5D4C 00000014 00025A39 00000008 000FE348 <UnitNo> -> FC03(64515)<PACKET_HEADER> ->00140700 <PACKET_NUMBER> ->00007D04 (32004)<DATE> -> 0002E702(190210)<TIME> -> 0001624F(90703)<lat> -> 00C02A9D(12593821) <lan> -> 049C5D4C(77356364) <speed> ->00000014(20)<pulseodometer> -> 00025A39 (<RESERVED> -> 00000008<IO1> -> 000FE348 How should i modify the query? I have 11 fields . |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-29 : 05:12:25
|
first, you use the same function fnParseString() to parse the string, pass in ' ' as delimiter. Then you need to convert the hex string to decimal.Here are a couple of them from google resulthttp://blog.sqlauthority.com/2010/02/01/sql-server-question-how-to-convert-hex-to-decimal/http://beyondrelational.com/modules/2/blogs/70/posts/10888/converting-hexadcimal-to-decimal.aspx KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-29 : 05:21:12
|
Thanksselect gps_data, no_of_sets = case when gps_data like '^%' then (len(gps_data) - len(replace(gps_data, '|', ''))) / 5 else (len(gps_data) - len(replace(gps_data, ',', '')) + 1) / 5 end, UnitNo = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 6), '|', gps_data) else dbo.fnParseString(-((num * 5) + 1), ',', gps_data) end, lat = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 4), '|', gps_data) else dbo.fnParseString(-((num * 5) + 2), ',', gps_data) end, lon = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 5), '|', gps_data) else dbo.fnParseString(-((num * 5) + 3), ',', gps_data) end, IO1 = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 3), '|', gps_data) else dbo.fnParseString(-((num * 5) + 4), ',', gps_data) end, IO2 = case when gps_data like '^%' then dbo.fnParseString(-((num * 5) + 2), '|', gps_data) else dbo.fnParseString(-((num * 5) + 5), ',', gps_data)In the above query is '5' the maximum no of substrings and are other numbers the position of the substring ? |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-29 : 05:32:25
|
If cmdstr = 'FC03 00140700 00007D04 0002E702 0001624F 00C02A9D 049C5D4C 00000014 00025A39 00000008 000FE348'select CmdStr, no_of_sets = case when CmdStr like '^%' then (len(CmdStr) - len(replace(CmdStr, '', ''))) / 11 //else (len(CmdStr) - len(replace(CmdStr, ',', '')) + 1) / 11 end, UnitNo = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 1), '', CmdStr) //else dbo.fnParseString(-((num * 11) + 1), ',', CmdStr) end, packet_header= case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 2), '', CmdStr) // else dbo.fnParseString(-((num * 11) + 2), ',', CmdStr) end, packet_number = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 3), ' ', CmdStr) // else dbo.fnParseString(-((num * 11) + 3), ',', CmdStr) end, datef = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 4), ' ', CmdStr) // else dbo.fnParseString(-((num * 11) + 4), ',', CmdStr) end, timef = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 5), ' ', CmdStr) // else dbo.fnParseString(-((num * 11) + 5), ',', CmdStr) end lat= case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 6), ' ', CmdStr) // else dbo.fnParseString(-((num * 11) + 6), ',', CmdStr) endfrom RawDataPackets inner join numbers n on n.num >= 0 and n.num < case when CmdStr like '^%' then (len(CmdStr) - len(replace(CmdStr, '', ''))) / 11 else (len(CmdStr) - len(replace(CmdStr, ',', '')) + 1) / 11 end end==============================================================================Is the above query correct to get unitno packet_header packet_number datef timef lat FC03 00140700 00007D04 0002E702 0001624F 00C02A9D |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-29 : 05:33:37
|
you need to change this accordinglythe earlier is only 5 value per sets, this new one is 11 fields.no_of_sets = case when gps_data like '^%' then (len(gps_data) - len(replace(gps_data, '|', ''))) / 5 else (len(gps_data) - len(replace(gps_data, ',', '')) + 1) / 5 end, if you have a Device Type or something to identify various format, use it to. then (len(gps_data) - len(replace(gps_data, '|', ''))) / case when device = 'device-1' then 5 when device = 'device-2' then 5 when device = 'device-3' then 11 end KH[spoiler]Time is always against us[/spoiler] |
|
|
abk
Starting Member
29 Posts |
Posted - 2012-03-29 : 05:52:07
|
I did change to 11 , but I am not able to get the result. Dont know if I am missing something. I am just trying it on one string only FC03 00140700 00007D04 0002E702 0001624F 00C02A9D 049C5D4C 00000014 00025A39 00000008 000FE348=========================================================The query usedselect CmdStr, no_of_sets = case when CmdStr like '^%' then (len(CmdStr) - len(replace(CmdStr, '', ''))) / 11 else (len(CmdStr) - len(replace(CmdStr, ',', '')) + 1) / 11 end, UnitNo = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 1), '', CmdStr) else dbo.fnParseString(-((num * 11) + 1), ',', CmdStr) end, packet_header= case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 2), '', CmdStr) else dbo.fnParseString(-((num * 11) + 2), ',', CmdStr) end, packet_number = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 3), '', CmdStr) else dbo.fnParseString(-((num * 11) + 3), ',', CmdStr) end, datef = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 4), '', CmdStr) else dbo.fnParseString(-((num * 11) + 4), ',', CmdStr) end, timef = case when CmdStr like '^%' then dbo.fnParseString(-((num * 11) + 5), '', CmdStr) else dbo.fnParseString(-((num * 11) + 5), ',', CmdStr) endfrom RawDataPackets inner join numbers n on n.num >= 0 and n.num < case when CmdStr like '^%' then (len(CmdStr) - len(replace(CmdStr, '', ''))) / 11 else (len(CmdStr) - len(replace(CmdStr, ',', '')) + 1) / 11 end end |
|
|
khtan
In (Som, Ni, Yak)
17689 Posts |
Posted - 2012-03-29 : 06:01:38
|
that 11 fields is only part of the changes.... you still need to change the rest correspondingly.do you have a device type in your table that can identity which gps data is from which device type ? KH[spoiler]Time is always against us[/spoiler] |
|
|
Next Page
|
|
|
|
|