Got a table that contains a field similar to the following
856655.460000000000000+0.000000000000000+2200121.020000000000000
164171.720000000000000+0.000000000000000+421637.020000000000000
0.000000000000000+0.000000000000000+0.000000000000000+0.000000000000000
103176.220000000000000+0.000000000000000+264984.210000000000000
What I need to do is extract the numeric fields and total them. There may be a different number of numeric fields within the column, but they'll all be separated by the '+' symbol
Any help would be appreciated
Try this. to get a better answer you should add more detail about how the table is structured.
DECLARE #val VARCHAR(MAX) = '856655.460000000000000+0.000000000000000+2200121.020000000000000+164171.720000000000000+0.000000000000000+421637.020000000000000+0.000000000000000+0.000000000000000+0.000000000000000+0.000000000000000+103176.220000000000000+0.000000000000000+264984.210000000000000';
DECLARE #newVal VARCHAR(MAX);
CREATE TABLE #Table
(
value DECIMAL(30, 15)
);
WHILE LEN(#val) > 0
BEGIN
IF(#val LIKE '%+%')
BEGIN
SET #newVal = LEFT(#val, CHARINDEX('+', #val));
INSERT INTO #table
VALUES
(
CONVERT( DECIMAL(30, 15), LEFT(#newVal, LEN(#newVal) - 1))
);
SET #val = SUBSTRING(#val, LEN(#newVal)+1, LEN(#Val)-LEN(#newVal));
END;
ELSE
BEGIN
INSERT INTO #Table
VALUES
(
CONVERT( DECIMAL(30, 15), REPLACE(#val, '+', ''))
);
SET #val = '';
END;
END;
SELECT * FROM #Table
SELECT sum(value) FROM #Table;
DROP TABLE #Table
Edit:
To retrofit this to work on a table you could add a cursor which loops through each row in your table, runs the above query and updates the table with the results from the sum. I'm sure there are better ways but if this is a one time cleanup, it should work. Cheers
Clearly you will have to modify this to fit your situation, but the basic concept is to transform your plus sign separated string into xml and then use the nodes method to break it apart.
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL DROP TABLE #temp;
declare #string varchar(250)
declare #xml xml
set #string = '856655.460000000000000+0.000000000000000+2200121.020000000000000'
set #xml = ('<r>' + REPLACE(#string,'+','</r><r>') + '</r>')
select t.v.value('r[1]', 'decimal(25,15)') as Value1,
t.v.value('r[2]', 'decimal(25,15)') as Value2,
t.v.value('r[3]', 'decimal(25,15)') as Value3,
t.v.value('r[4]', 'decimal(25,15)') as Value4
into #temp
from #xml.nodes('/') AS t(v)
select *
from #temp
select coalesce(Value1, 0) + coalesce(Value2, 0) +
coalesce(Value3, 0) + coalesce(Value4, 0) as 'Total'
from #temp
You will have to add more code to the query that selects into #temp for each potential value in your string. If you have a massive amount of possible numbers this may not scale.
Hope this helps you get to what you need.
Related
I have a column in table which has multiple values separated by space.
i want to return those rows which has any of the matching values from search string.
Eg:
search string= 'mumbai pune'
This need to return rows matching word 'mumbai' or 'pune' or matching both
Declare #str nvarchar(500)
SET #str='mumbai pune'
create table #tmp
(
ID int identity(1,1),
citycsv nvarchar(500)
)
insert into #tmp(citycsv)Values
('mumbai pune'),
('mumbai'),
('nagpur')
select *from #tmp t
select *from #tmp t
where t.citycsv like '%'+#str+'%'
drop table #tmp
Required Out put:
ID CityCSV
1 mumbai pune
2 mumbai
You can use a splitter function to split your search string out as a table contain the desired search keys. Then you can join your main table with the table containing the search key using the LIKE statement.
For completeness I have included an example of a string splitter function, however there are plenty of example here on SO.
Example string splitter function:
CREATE FUNCTION [dbo].[SplitString]
(
#string NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE #start INT, #end INT
SELECT #start = 1, #end = CHARINDEX(#delimiter, #string)
WHILE #start < LEN(#string) + 1 BEGIN
IF #end = 0
SET #end = LEN(#string) + 1
INSERT INTO #output (splitdata)
VALUES(SUBSTRING(#string, #start, #end - #start))
SET #start = #end + 1
SET #end = CHARINDEX(#delimiter, #string, #start)
END
RETURN
END
The following query demonstrates how the string splitter function can be combined with regular expressions to get the desired result:
SELECT DISTINCT
C.ID
,C.citycsv
FROM #tmp C
INNER JOIN (
SELECT splitdata + '[ ]%' AS MatchFirstWord -- Search pattern to match the first word in the string with the target search word.
,'%[ ]' + splitdata AS MatchLastWord -- Search pattern to match the last word in the string with the target search word.
,'%[ ]' + splitdata + '[ ]%' AS MatchMiddle -- Search pattern to match any words in the middle of the string with the target search word.
,splitdata AS MatchExact -- Search pattern for exact match.
FROM dbo.SplitString(#str, ' ')
) M ON (
(C.citycsv LIKE M.MatchFirstWord) OR
(C.citycsv LIKE M.MatchLastWord) OR
(C.citycsv LIKE M.MatchMiddle) OR
(C.citycsv LIKE M.MatchExact)
)
ORDER BY C.ID
Another approach , by using ReplaceFunction
Its syntax as following:
REPLACE ( string_expression , string_pattern , string_replacement )
so we could reach the target via replacing the every space that separated the values with the next pattern
'%'' OR t.citycsv like ''%'
An example:
Declare #str nvarchar(500),
#Where nvarchar (1000),
#Query nvarchar (4000)
SET #str='mumbai pune'
create table #tmp
(
ID int identity(1,1),
citycsv nvarchar(500)
)
insert into #tmp(citycsv)Values
('mumbai pune'),
('mumbai'),
('nagpur')
select * from #tmp t
Set #Where = 'where t.citycsv like ' + '''%'+ replace (RTRIM(LTRIM(#str)), ' ', '%'' OR t.citycsv like ''%') +'%'''
Set #Query = 'select * from #tmp t ' + #Where
execute sp_executesql #Query
drop table #tmp
The Result:
I am working on SQL Server 2008 to create a stored procedure that:
takes a string variable like this: '1,2,3'
splits the string using a table-valued function to get each value separately
and then inserts each value into a new row in a table
What I am trying to do is something like this:
WHILE (select vlaue FROM dbo.SplitString('1,2,3',',')) has rows
insert into TableName (col1,col2) values (col1Data, value)
I am having a hard time trying to find the right syntax for this.
I use this Table-valued function:
CREATE FUNCTION [dbo].[Split] (#sep char(1), #s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(#sep, #s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(#sep, #s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(#s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
Which takes a string with a separator and returns a table with two columns the first returns a 1-based position and the second the element at that position in the string:
Usage:
SELECT * FROM dbo.Split(',', '1,2,3')
Returns:
pn s
1 1
2 2
3 3
To Insert results into a table:
INSERT INTO TableName (Col1)
SELECT S FROM dbo.Split(',', '1,2,3)
For your specific example change your syntax to be:
insert into TableName (col1,col2)
select col1Data, value FROM dbo.SplitString('1,2,3',',')
The typical INSERT INTO ... SELECT ... should do:
INSERT INTO TableName (col1,col2)
SELECT #col1Data,value FROM dbo.SplitString('1,2,3',','))
If someone else is looking for this, I was about to make a split function as several answers mentioned but noticed there's a built-in function that does this already.
string_split was added in MSSQL 2016.
INSERT INTO Project.FormDropdownAnswers (FkTableId, CreatedBy, CreatedDate)
SELECT 123, TRY_CAST(value AS INT), #username, getdate()
FROM string_split('44,45,46,47,55',',')
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
CREATE TABLE tablename
(
id SMALLINT ,
value INT
)
INSERT INTO tablename ( id, value )
SELECT * FROM dbo.Split('1,2,3',',')
try this....
If need to use as variables there is 2 nice options:
Procedure MF_SPLIT
CREATE PROC [MF_SPLIT] (#ELS NVARCHAR(MAX)=NULL OUTPUT, #RET NVARCHAR(MAX)=NULL OUTPUT, #PROC NVARCHAR(MAX)=NULL) AS BEGIN
IF #ELS IS NULL BEGIN
PRINT ' #ELS
List of elements in string (OUTPUT)
#RET
Next return (OUTPUT)
#PROC
NULL = '','', content to do split
Example:
DECLARE #NAMES VARCHAR(100) = ''ERICK,DE,VATHAIRE''
DECLARE #N VARCHAR(100)
WHILE #NAMES IS NOT NULL BEGIN
EXEC MF_SPLIT #NAMES OUTPUT, #N OUTPUT
SELECT List = #NAMES, ActiveWord = #N
END'
RETURN
END
SET #PROC = ISNULL(#PROC, ',')
IF CHARINDEX(#PROC, #ELS) = 0 BEGIN
SELECT #RET = #ELS, #ELS = NULL
RETURN
END
SELECT
#RET = LEFT(#ELS, CHARINDEX(#PROC, #ELS) - 1)
, #ELS = STUFF(#ELS, 1, LEN(#RET) + 1, '')
END
Usage:
DECLARE #NAMES VARCHAR(100) = '1,2,3'
DECLARE #N VARCHAR(100)
WHILE #NAMES IS NOT NULL BEGIN
EXEC MF_SPLIT #NAMES OUTPUT, #N OUTPUT
SELECT List = #NAMES, ActiveWord = #N
END
Procedure MF_SPLIT_DO (Depends of MF_SPLIT), less sintax to use BUT the code will be in a string and use default variable "#X"
CREATE PROC MF_SPLIT_DO (#ARR NVARCHAR(MAX), #DO NVARCHAR(MAX)) AS BEGIN
--Less sintax
DECLARE #X NVARCHAR(MAX)
WHILE #ARR IS NOT NULL BEGIN
EXEC MF_SPLIT #ARR OUT, #X OUT
EXEC SP_EXECUTESQL #DO, N'#X NVARCHAR(MAX)', #X
END
END
Usage:
EXEC MF_SPLIT_DO '1,2,3', 'SELECT #X'
I have a table which contains a column named NUMBERS which has the values 1234, 1235, 1278, 4567, 5434, and 7890. I am trying to write a procedure that will SELECT all values that begin with a number #NUMBER.
I was thinking it would look something like this:
DECLARE #NUMBER as int
SET #NUMBER = 1
SELECT * FROM table1 WHERE [NUMBER] LIKE (#NUMBER + '%')
But that is giving me an error 'Conversion failed when converting the varchar value '%' to data type int'.
How can I make it so that if I enter 1 as my #NUMBER it will return everything that begins with 1 (i.e. 1234, 1235, 1278)
You need to convert numbers to strings so the + operator is understood to be string concatenation (rather than addition):
SELECT *
FROM table1
WHERE cast([NUMBER] as varchar(255)) LIKE cast(#NUMBER as varchar(255)) + '%';
Because like does an implicit cast() anyways, you should be explicit about what the query is doing. I add a cast to the first part as well.
Note: You could also fix this by changing the declaration of the variable:
DECLARE #NUMBER as varchar(255);
SET #NUMBER = '1';
SELECT * FROM table1 WHERE [NUMBER] LIKE (#NUMBER + '%');
I have a space separated string as parameter to my SP. I need to split the strings and compare each one against a column in the database along with wildcard and return the results.
For example:
I have CompanyName 'ABC DataServices Pvt Ltd' I need to split the string by 'space' and compare each word with database field company name with an OR condition.
Something like this:
select *
from CompanyTable
where companyname like '%ABC%'
or companyname like '%DataServices%'
or companyname like '%Pvt%'
or companyname like '%Ltd%'
Can some one help me out to achieve this?
Thanks in advance
Try this SQL User Defined Function to Parse a Delimited String helpful .
For Quick Solution use this ,
SELECT PARSENAME(REPLACE('ABC DataServices Pvt Ltd', ' ', '.'), 2) // return DataServices
PARSENAME takes a string and splits it on the period character. It takes a number as it's second argument, and that number specifies which segment of the string to return (working from back to front).
you can put the index you want in place of 2 in above like
SELECT PARSENAME(REPLACE('ABC DataServices Pvt Ltd', ' ', '.'), 3) --return Pvt
declare a string in your store procedure and use set this value to it. use where you want.
The only problem is when the string already contains a period. One thing should be noted that PARSENAME only expects four parts, so using a string with more than four parts causes it to return NULL
Try this function:
CREATE FUNCTION [dbo].[fnSplitString]
(
#string NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE #start INT, #end INT
SELECT #start = 1, #end = CHARINDEX(#delimiter, #string)
WHILE #start < LEN(#string) + 1 BEGIN
IF #end = 0
SET #end = LEN(#string) + 1
INSERT INTO #output (splitdata)
VALUES(SUBSTRING(#string, #start, #end - #start))
SET #start = #end + 1
SET #end = CHARINDEX(#delimiter, #string, #start)
END
RETURN
END
And use it like this:
select * from dbo.fnSplitString('Querying SQL Server','')
This will scale to any number of search terms and does not require dynamic SQL.
declare #a table (w varchar(50)) -- holds original string
declare #b table (s varchar(50)) -- holds parsed string
insert into #a -- load string into temp table
values ('ABC DataServices Pvt Ltd')
--parse string as XML
;WITH Vals AS (
SELECT w,
CAST('<d>' + REPLACE(w, ' ', '</d><d>') + '</d>' AS XML) XmlColumn
FROM #a
)
--Insert results to parsed string
insert into #b
SELECT
C.value('.','varchar(max)') ColumnValue
FROM Vals
CROSS APPLY Vals.XmlColumn.nodes('/d') AS T(C)
--Join on results
select * from companytable
join #b b on b.s like '%'+companyname+'%'
You can also try this.
First in your parameter's value replace space with comma (,) and then replace comma with desired where condition like this -
DECLARE #companyname VARCHAR(1000)
,#where VARCHAR(max)
SET #companyname = 'ABC DataServices Pvt Ltd'
SET #companyname = replace(#companyname, ' ', ', ')
SELECT #where = 'companyname like ''%' +
REPLACE(#companyname, ', ', '%'' OR companyname like ''%') + '%'''
PRINT #where
PRINT ('SELECT * FROM CompanyTable WHERE' + #where)
--EXEC ('SELECT * FROM CompanyTable WHERE' + #where)
In SQL Server, I am passing String as parameter :
#Param1 = Test,Test1,Test2
I am formatting it to:
#Param1 = 'Test','Test1','Test2'
When I am trying to use this in SELECT statement with IN parameter, it is not returning any data
SELECT * FROM TABLE1 where COLUMN1 IN (#Param1)
What is the correct syntax?
As pointed out already in the comments by marc_s, IN requires a list of values not simply one variable.
But you could provide those values in a SELECT from a simple table variable like this:
DECLARE #Param1 TABLE (Value NVARCHAR(255));
INSERT INTO #Param1 (Value)
SELECT 'Test1'
UNION
SELECT 'Test2'
UNION
SELECT 'Test3'
SELECT
*
FROM TABLE1
WHERE
COLUMN1 IN
(SELECT Value FROM #Param1)
I wish there were array vars like that! :-)
But you can convert it to a table using a function, and then use the table with your IN clause as you're attempting.
Here is how that would look:
DECLARE #Param1 nvarchar(max)
SET #Param1 = 'Test,Test1,Test2'
SELECT *
FROM myTable
WHERE myField In (Select ParsedString From dbo.ParseStringList(#Param1))
And here is (at least one way to write) the function:
CREATE Function [dbo].[ParseStringList] (#StringArray nvarchar(max) )
Returns #tbl_string Table (ParsedString nvarchar(max)) As
BEGIN
DECLARE #end Int,
#start Int
SET #stringArray = #StringArray + ','
SET #start=1
SET #end=1
WHILE #end<Len(#StringArray)
BEGIN
SET #end = CharIndex(',', #StringArray, #end)
INSERT INTO #tbl_string
SELECT
Substring(#StringArray, #start, #end-#start)
SET #start=#end+1
SET #end = #end+1
END
RETURN
END