How to convert string of numbers ( '14, 72' ) to numbers in sql query - sql

declare #lkaklf as varchar(Max)
Select ss.Data from SplitString('14,72', ',') as ss
Select #lkaklf = CONVERT(varchar, COALESCE( + #lkaklf + ',', '') + '''' + Data + '''') From
(
Select Data from SplitString('14,72', ',')
)de
select #lkaklf
print #lkaklf
Select * from LPO Where CONVERT(varchar, LPO.LocalPurchaseOrderId) in (#lkaklf)
#lkalf value is Printing in message but not coming into select query... Why ?

You cannot do what you want. I would recommend that you skip over the splitting part of the query and just do:
where ','+#lkaklf+',' like ','+cast(LPO.LocalPurchaseOrderId as varchar(255))+',%'
That is, just use string comparisons.
If you really want to use SplitString(), then put the results in a temporary table:
insert into #t
select data from splitstring('14,72', ',')
And then use a subquery:
where cast(#lkalklf as varchar(255)) in (select data from #t)

Related

SQL Pivot - take a changing date from column and make it a row header

I have a basic query that looks like this.
SELECT Database_Name,
FilingDate,
SUM(ISNULL([column1], 0) + ISNULL(column2], 0) +
ISNULL([column3], 0) + ISNULL([column4], 0)) AS Total
FROM SomeTable(NOLOCK)
GROUP BY Database_Name,
FilingDate
ORDER BY Database_Name,
FilingDate DESC
This query outputs results that look like this.
I would like to take the dates returned in the FilingDate column and use them as new column headers with the totals for each database and date being used as the row content. The end result should look like this:
My research suggests that a pivot is the best option but I'm struggling to find the right way to execute it as my dates change each day Any assistance would be appreciated.
If this is MS SQL, you can use a dynamic pivot table. Here is a solution using your query (should work, but I don't have the base data to test it).
SELECT Database_Name,
FilingDate,
SUM( ISNULL(column1 ,0) +
ISNULL(column2],0) +
ISNULL([column3],0) +
ISNULL([column4],0)
) AS Total
INTO #T1
FROM SomeTable(NOLOCK)
GROUP BY Database_Name,
FilingDate
DECLARE #PivotColumnHeaders varchar(MAX)
SELECT #PivotColumnHeaders =
COALESCE(
#PivotColumnHeaders + ',[' + CAST(UC.FilingDate AS NVARCHAR(10)) + ']',
'[' + CAST(UC.FilingDate AS NVARCHAR(10)) + ']'
)
FROM (SELECT FilingDate FROM #T1 GROUP BY FilingDate) UC
DECLARE #PQuery varchar(MAX) = '
SELECT * FROM (SELECT Database_Name, FilingDate, Total FROM #T1 T0) T1
PIVOT (SUM([Total]) FOR FilingDate IN (' + #PivotColumnHeaders + ') ) AS P'
EXECUTE (#PQuery)
DROP TABLE #T1

SQL IN Statement splitting parameter

SQL Server
I have a parameter that contains a comma delimited string:
'abc,def,ghi'
I want to use that string in a IN statement that would take my parameter like this:
select * from tableA where val IN ('abc','def','ghi')
Any ideas on how I would do this?
If using dynamic SQL is an option, this can be executed:
SELECT 'SELECT * FROM tableA WHERE val IN (' +
'''' + REPLACE('abc,def,ghi', ',', ''',''') + ''')'
Basically, the REPLACE() function separates each item by ',' instead of just ,.
The simplest way would be to do something like this:
SELECT *
FROM TableName
WHERE ',' + commaDelimitedString + ',' LIKE '%,' + FieldName + ',%'
But be careful about SQL injection. You might want to parameterize it.
You can use this SQL to 'pivot' a comma-separated string into a table;
DECLARE #badData TABLE (id INT NOT NULL, txt NVARCHAR(max));
INSERT INTO #badData
VALUES (1, 'foo,bar,baz'), (2, NULL);;
-- the idea is to recursively 'pop' a value from the start of the string, splitting it into 'head' and 'tail' components
WITH unpacked (id, head, tail)
AS (
SELECT id, LEFT(txt, CHARINDEX(',', txt + ',') - 1), STUFF(txt, 1, CHARINDEX(',', txt + ','), '')
FROM #badData
UNION ALL
SELECT id, LEFT(tail, CHARINDEX(',', TAIL + ',') - 1), STUFF(tail, 1, CHARINDEX(',', tail+ ','), '')
FROM unpacked
WHERE tail > ''
)
SELECT id, head
FROM unpacked
ORDER BY id
You could stick this result into a common table expression, then write a where clause like
select * from tableA where val IN (select head from unpacked)
heavily plagiarised from https://stackoverflow.com/a/5493616/6722
Many programming languages have a split() function, for example in Ruby
'123,456,789'.split ","
=> ["123", "456", "789"]

With IN Clause when Passing Collection as Parameter In Sql Server

Query Gives O/p as
ItemSizeNM
(colName)
'U','V','X','Y'
But when I used this as input to IN Query in the Code Which I did.
It Doesn't Gives same resultset. Why This Happens...?
Table MstItemSize Has Proper Data.
declare #tblRingSize table ( ringSize varchar(100))
declare #ringSize varchar(100)
select #ringSize= cast((otherringSize) as varchar)
from ##tempBand where styleNo='BD00002';
INSERT INTO #tblRingSize SELECT Item FROM dbo.SplitStrings_CTE (#ringSize, ',');
select ItemSizeNm from MstItemSize where SizeTypeNm ='Ring' and
ItemSizeNm
in --('U','V','X','Y')
( select Replace (
(select STUFF( (select ''',''' + ringSize from #tblRingSize For XML PATH('')),1,2,'') +'''' )
,' ',''))
select Replace (
(select STUFF( (select ''',''' + ringSize from #tblRingSize For XML PATH('')),1,2,'') +'''' )
,' ','')
You don't need to use STUFF, FOR XML, or REPLACE for the subquery:
select
ItemSizeNm
from
MstItemSize
where SizeTypeNm ='Ring'
and ItemSizeNm in (select ringSize from #tblRingSize)

How to generate an update query of a dynamic query (automatically)?

I'm storing some queries in a table column so I can execute them later passing some parameters.
But it has been really annoying to format the query into an Update sentence, because of the special characters.
For Example:
SELECT * FROM MOUNTAINS WHERE MON_NAME='PALMA' AND MON_DESC LIKE '%TRANVULCANIA%'
Then I need the string just for the udpate query:
UPDATE QUERIES
SET QUE_SEL='SELECT * FROM MOUNTAINS WHERE MON_NAME='''+'PALMA'+''' AND MON_DESC LIKE '''+'%TRANVULCANIA%'+''' '
WHERE QUE_ID=1
as you can see the first ' must be replaced for '''+' but the next door ' must be replaced by '+'''
This is the query I'm working on:
DECLARE #QUERY VARCHAR(MAX)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''' '
SELECT
t.r.value('.', 'varchar(255)') AS token
, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
this is the result:
token id
-------------------------------------------------- --------------------
SELECT * FROM QUERIES WHERE QUE_NOMBRE= 1
' 2
PRUEBA 1 3
' 4
5
Now I want a column that tell me when to open and when to close and then I can set the final replace.
Adapting the solution given by #rivarolle
DECLARE #QUERY VARCHAR(MAX)
DECLARE #FORMATTED varchar(max)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''
;WITH TOKENS AS(
SELECT
t.r.value('.', 'varchar(MAX)') AS token
, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
)
,
Tokens2 as (
SELECT
TOKENS.token as token
,quotes.row%2 as tipoapostrofe
from Tokens
left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes
on quotes.Id = Tokens.Id
)
SELECT #FORMATTED = STUFF((
SELECT ' ' + REPLACE(token,'''',CASE tipoapostrofe WHEN 1 THEN '''''''+''' WHEN 0 THEN '''+''''''' ELSE '' END) AS [text()]
FROM Tokens2
FOR XML PATH('')
), 1, 1, '')
print #FORMATTED
This Works, just need a function for cleaning XML special characters and another for putting back, and the Dynamic queries are printed ready for an update.
I think its not necessary to replace an apostrophe with '''+' to open and '+''' to close, I made some probes and you can exec a query that you replace opening and closing apostrophes with the same.. for example '''+' for open and '''+' for close.
So the query would be:
DECLARE #QUERY VARCHAR(MAX)
DECLARE #FORMATTED varchar(max)
SELECT #QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''
SELECT #FORMATTED= STUFF((
SELECT ' ' +
(SELECT
CASE
WHEN t.r.value('.', 'varchar(250)')='''' THEN REPLACE(t.r.value('.', 'varchar(250)'), '''','''''''+''')
ELSE t.r.value('.', 'varchar(250)')
END
) AS [text()]
-- , ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
FROM (
SELECT myxml = CAST('<t>' + REPLACE(#QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
) p
CROSS APPLY myxml.nodes('/t') t(r)
FOR XML PATH('')
), 1, 1, '')
SET #FORMATTED=REPLACE(#FORMATTED,' ','')
PRINT #FORMATTED
then I get:
SELECT * FROM QUERIES WHERE QUE_NOMBRE= '''+' PRUEBA 1 '''+'
then I copy into a variable and execute
DECLARE #VAR VARCHAR(500)
SET #VAR='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'''+' '
EXEC(#VAR)
It Works for very simple queries, but with longer and complicated queries it doesn't works..
Assuming your token table is Tokens(Token, Id, Position):
update Tokens
set position = quotes.row%2
from Tokens
left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes
on quotes.Id = Tokens.Id
The position column will have a value of 1 for starting quote and 0 for closing quote. NULL for the rest.

What is the best way to collapse the rows of a SELECT into a string?

In a SQL statement ( or procedure ) I want to collapse the rows of this table into a single comma delimited string.
simpleTable
id value
-- -----
1 "a"
2 "b"
3 "c"
Collapse to:
"a, b, c"
You can concatenate using an embedded 'set' statement in a query:
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + isnull(value,'')
from simpleTable
print #combined
(Note that the first isnull() initialises the string, and the second isnull() is especially important if there's any chance of nulls in the 'value' column, because otherwise a single null could wipe out the whole concatenation)
(edited code and explanation after comments)
Edit (ten years later):
SQL Server 2017 introduced the STRING_AGG() function which provides an official way of concatenating strings from different rows. Like other aggregation functions such as COUNT(), it can be used with GROUP BY.
So for the example above you could do:
select string_agg(value, ', ')
from simpleTable
If you had some other column and you wanted to concatenate for values of that column, you would add a 'group by' clause, e.g:
select someCategory, string_agg(value, ', ') as concatValues
from simpleTable
group by someCategory
Note string_agg will only work with SQL 2017 and above.
This will only work in MSSQL 2005+
select value + ',' from simpletable for xml path ('')
..one way to prevent the extra comma:
select case(row_number() over (order by id))
when 1 then value else ',' + value end
from simpletable
for xml path ('')
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
Results:
1, 2, 4
This is based on #codeulike answer, but will prevent losing the portion of the string that gets concatenated before a null "value" is concatenated on.
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + ISNULL(value,'')
from simpleTable
print #combined