I need to modify/cut some characters from my variable #txt
The variable is declared like this:
DECLARE #txt VARCHAR(MAX)
and #txt is a long string.
I need to cut and move this marked fragment in blue (screenshot)
How can I do this? Could you please give me some advice that will help me?
enter image description here
Use your data cleverly. We assume that values in 1st and 2nd fields (eg Corp and 111EF111) are variable length.
Therefore, we search for the - in the date, and then for the 3rd comma after it:
SELECT CHARINDEX('-', #txt) + 15 AS Index_First_Date_Dash
,CHARINDEX(',',#txt, CHARINDEX('-', #txt) + 15 + 12) AS Index_3rd_Comma_After_Time
,SUBSTRING(#txt,1,CHARINDEX(',',#txt, CHARINDEX('-', #txt) + 15 + 12)) AS Extract
Related
I have attachments table which has GPSLatitude and GPSLongitude columns for each attachment. It's legacy code which is populating the fields and the values looks like:
GPSLatitude
50/1,5/1,1897/100
GPSLongitude
14/1,25/1,4221/100
Is there any build in function which I can use in order to convert them to latitude and longitude decimal values like this:
Location Latitude
41.5803
Location Longitude
-83.9124
I can implement SQL CLR function if this can be done easier with .net also.
What is most difficult for me right now is to understand what these values represent. The legacy code is using some API with no documentation about the returned format and how to read it.
The values above are just for showing how the data is formatted. The following library is used to get the values - chestysoft like this:
IF Image.ExifValueByName("GPSLatitude") <> "" THEN GPSLatitude = Image.ExifValueByName("GPSLatitude") ELSE GPSLatitude = NULL END IF
IF Image.ExifValueByName("GPSLongitude") <> "" THEN GPSLongitude = Image.ExifValueByName("GPSLongitude") ELSE GPSLongitude = NULL END IF
I'm fairly certain you should read it as:
50/1: 50 Degrees
5/1: 5 Minutes
1897/100: 18.97 Seconds
This would put the location you've given in New York (assuming N/W), does that make sense? If you have no way to validate the output it's very difficult to make any other suggestion... See also here
In the link you provided, you can upload a picture to view the exif data. There you can test with known locations. It is also apparent that in the values you mentioned, the GPSLatitudeRef and GPSLongitudeRef are missing. You need these to change the values to a location. Do you have those values in your table? Otherwise you'll have to make (wild) assumptions.
This is by the way the standard EXIF notation for latitude/longitude; I assume there are many, many tools to convert it.
Assuming that #Cool_Br33ze is correct, and the data is in degrees, minutes and seconds, you can calculate the values you need using the following:
declare #v varchar(30) = '50/1,5/1,1897/100'
select #v Original_Value,
convert(decimal(18,4), left(#v, charindex('/', #v) - 1)) [Degrees],
convert(decimal(18,4), substring(
#v,
charindex(',', #v) + 1,
charindex('/', #v, charindex(',', #v)) - (charindex(',', #v) + 1)
) / 60.0
) [Minutes],
convert(decimal(18,4), substring(
#v,
charindex(',', #v, (charindex(',', #v) + 1)) + 1,
charindex('/', #v, charindex(',', #v, (charindex(',', #v) + 1))) - (charindex(',', #v, (charindex(',', #v) + 1)) + 1)
) / 360000.0
) [Seconds]
It looks a bit of a mess, but it splits out the degrees, minutes and seconds (converted to DECIMAL(18,4)), all you need to do is add the three values together to get your Lat/Long value in degrees.
I'd test it thoroughly before implementing it though.
I have the following field called "MaterialPrice". It is a data type of -
DECIMAL (18,2)
So a sample values is "10.88"
What I need to change it to is something like below -
0000000000000**1088**0
So the field length is 18, where the last character (to the left is always 0) and the characters in front of the original value are padded with zeros also.
Another example would be
501.02
would be
000000000000**50102**0
Any help would be appreciated.
Thanks
If I understand correctly the requirement, you could as the below:
DECLARE #val DECIMAL(18, 2) = 501.02
SELECT REPLICATE(0, 18 - LEN(#val)) + '**' + REPLACE(CAST(#val AS VARCHAR(50)), '.', '') + '**0'
Result: 000000000000**50102**0
I would:
Multiply by 100,
cast to string,
Measure length,
Concatenate: (17-length) "0"s, "**", the string number and "**0
I have data in a text column that looks like xxxxx.x.xx
I need to get the string into a view with a format of xxxxx.x (removing the trailing .xx).
I am not sure how to do this. Any help would be appreciated.
I think I would need to get the length from the start to the 2nd "." and then Left that length.
I also wonder, can this be done as a column expression or would it need a function?
Here is another twist. How would I handle the same issue if the char length is variable such as xxxxxx.xx.x and xxxxx.x.x?
You can also try this:
SELECT
REVERSE(
SUBSTRING(
REVERSE(#word),
CHARINDEX('.', REVERSE(#word))+1,
LEN(REVERSE(#word))
)
)
FROM yourTable
Here is a SQLFiddle
This solution is generic, so it would work also for the case in which you have xx.xxxx.xx.xxx or any other number of letters sepparated by dots.
This can be achieved using the expression:
left(#s, charindex('.', #s, charindex('.', #s) + 1) - 1)
(where #s is your varchar value)
Online demo: http://www.sqlfiddle.com/#!3/d41d8/23448
select 'xxxxx.x.xx' as original
,Replace( 'xxxxx.x.xx',Right('xxxxx.x.xx',3),'') as new
I have a customer table that I want to use to populate a parameter box in SSRS 2008. The cust_num is the value and the concatenation of the cust_name and cust_addr will be the label. The required fields from the table are:
cust_num int PK
cust_name char(50) not null
cust_addr char(50)
The SQL is:
select cust_num, cust_name + isnull(cust_addr, '') address
from customers
Which gives me this in the parameter list:
FIRST OUTPUT - ACTUAL
1 cust1 addr1
2 customer2 addr2
Which is what I expected but I want:
SECOND OUTPUT - DESIRED
1 cust1 addr1
2 customer2 addr2
What I have tried:
select cust_num, rtrim(cust_name) + space(60 - len(cust_name)) +
rtrim(cust_addr) + space(60 - len(cust_addr)) customer
from customers
Which gives me the first output.
select cust_num, rtrim(cust_name) + replicate(char(32), 60 - len(cust_name)) +
rtrim(cust_addr) + replicate(char(32), 60 - len(cust_addr)) customer
Which also gives me the first output.
I have also tried replacing space() with char(32) and vice versa
I have tried variations of substring, left, right all to no avail.
I have also used ltrim and rtrim in various spots.
The reason for the 60 is that I have checked the max length in both fields and it is 50 and I want some whitespace between the fields even if the field is maxed. I am not really concerned about truncated data since the city, state, and zip are in different fields so if the end of the street address is chopped off it is ok, I guess.
This is not a show stopper, the SSRS report is currently deployed with the first output but I would like to make it cleaner if I can.
Whammo blammo (for leading spaces):
SELECT
RIGHT(space(60) + cust_name, 60),
RIGHT(space(60) + cust_address, 60)
OR (for trailing spaces)
SELECT
LEFT(cust_name + space(60), 60),
LEFT(cust_address + space(60), 60),
The easiest way to right pad a string with spaces (without them being trimmed) is to simply cast the string as CHAR(length). MSSQL will sometimes trim whitespace from VARCHAR (because it is a VARiable-length data type). Since CHAR is a fixed length datatype, SQL Server will never trim the trailing spaces, and will automatically pad strings that are shorter than its length with spaces. Try the following code snippet for example.
SELECT CAST('Test' AS CHAR(20))
This returns the value 'Test '.
This is based on Jim's answer,
SELECT
#field_text + SPACE(#pad_length - LEN(#field_text)) AS RightPad
,SPACE(#pad_length - LEN(#field_text)) + #field_text AS LeftPad
Advantages
More Straight Forward
Slightly Cleaner (IMO)
Faster (Maybe?)
Easily Modified to either double pad for displaying in non-fixed width fonts or split padding left and right to center
Disadvantages
Doesn't handle LEN(#field_text) > #pad_length
Based on KMier's answer, addresses the comment that this method poses a problem when the field to be padded is not a field, but the outcome of a (possibly complicated) function; the entire function has to be repeated.
Also, this allows for padding a field to the maximum length of its contents.
WITH
cte AS (
SELECT 'foo' AS value_to_be_padded
UNION SELECT 'foobar'
),
cte_max AS (
SELECT MAX(LEN(value_to_be_padded)) AS max_len
)
SELECT
CONCAT(SPACE(max_len - LEN(value_to_be_padded)), value_to_be_padded AS left_padded,
CONCAT(value_to_be_padded, SPACE(max_len - LEN(value_to_be_padded)) AS right_padded;
declare #t table(f1 varchar(50),f2 varchar(50),f3 varchar(50))
insert into #t values
('foooo','fooooooo','foo')
,('foo','fooooooo','fooo')
,('foooooooo','fooooooo','foooooo')
select
concat(f1
,space(max(len(f1)) over () - len(f1))
,space(3)
,f2
,space(max(len(f2)) over () - len(f2))
,space(3)
,f3
)
from #t
result
foooo fooooooo foo
foo fooooooo fooo
foooooooo fooooooo foooooo
I have a string with a specific pattern:
23;chair,red [$3]
i.e., a number followed by a semicolon, then a name followed by a left square bracket.
Assuming the semicolon ; always exists and the left square bracket [ always exists in the string, how do I extract the text between (and not including) the ; and the [ in a SQL Server query? Thanks.
Combine the SUBSTRING(), LEFT(), and CHARINDEX() functions.
SELECT LEFT(SUBSTRING(YOUR_FIELD,
CHARINDEX(';', YOUR_FIELD) + 1, 100),
CHARINDEX('[', YOUR_FIELD) - 1)
FROM YOUR_TABLE;
This assumes your field length will never exceed 100, but you can make it smarter to account for that if necessary by employing the LEN() function. I didn't bother since there's enough going on in there already, and I don't have an instance to test against, so I'm just eyeballing my parentheses, etc.
Assuming they always exist and are not part of your data, this will work:
declare #string varchar(8000) = '23;chair,red [$3]'
select substring(#string, charindex(';', #string) + 1, charindex(' [', #string) - charindex(';', #string) - 1)
An alternative to the answer provided by #Marc
SELECT SUBSTRING(LEFT(YOUR_FIELD, CHARINDEX('[', YOUR_FIELD) - 1), CHARINDEX(';', YOUR_FIELD) + 1, 100)
FROM YOUR_TABLE
WHERE CHARINDEX('[', YOUR_FIELD) > 0 AND
CHARINDEX(';', YOUR_FIELD) > 0;
This makes sure the delimiters exist, and solves an issue with the currently accepted answer where doing the LEFT last is working with the position of the last delimiter in the original string, rather than the revised substring.
select substring(your_field, CHARINDEX(';',your_field)+1
,CHARINDEX('[',your_field)-CHARINDEX(';',your_field)-1)
from your_table
Can't get the others to work. I believe you just want what is in between ';' and '[' in all cases regardless of how long the string in between is. After specifying the field in the substring function, the second argument is the starting location of what you will extract. That is, where the ';' is + 1 (fourth position - the c), because you don't want to include ';'. The next argument takes the location of the '[' (position 14) and subtracts the location of the spot after the ';' (fourth position - this is why I now subtract 1 in the query). This basically says substring(field,location I want substring to begin, how long I want substring to be). I've used this same function in other cases. If some of the fields don't have ';' and '[', you'll want to filter those out in the "where" clause, but that's a little different than the question. If your ';' was say... ';;;', you would use 3 instead of 1 in the example. Hope this helps!
If you need to split something into 3 pieces, such as an email address and you don't know the length of the middle part, try this (I just ran this on sqlserver 2012 so I know it works):
SELECT top 2000
emailaddr_ as email,
SUBSTRING(emailaddr_, 1,CHARINDEX('#',emailaddr_) -1) as username,
SUBSTRING(emailaddr_, CHARINDEX('#',emailaddr_)+1, (LEN(emailaddr_) - charindex('#',emailaddr_) - charindex('.',reverse(emailaddr_)) )) domain
FROM
emailTable
WHERE
charindex('#',emailaddr_)>0
AND
charindex('.',emailaddr_)>0;
GO
Hope this helps.