How to get all records on the basis of Search String In sql - sql

I want to fetch all the records on the basis of Search string
E.G.
Column name: FileName
MasterRoomTwo.jpg
BedRoom.png
MasterbedRoom.gif
and in simple scenario I can use
Declare #FileName nvarchar(60) = NULL
set #FileName = '.jpg'
SELECT *
FROM JobAttachment
WHERE AND Tags LIKE '%' + ISNULL(#FileName ,FileName ) + '%'
ORDER BY updated DESC
but in my case I will get like
set #FileName = '.jpg,.Png,gif'
So how to make query like this?
Any help will be appreciated.
Thanks

Try this. Split the input string and use charindex
SELECT 'MasterRoomTwo.jpg' a INTO #temp UNION
SELECT 'BedRoom.png' UNION
SELECT 'MasterbedRoom.gif'
DECLARE #FileName NVARCHAR(60)
SET #FileName = '.jpg,.Png,gif'
SELECT *
FROM #temp
JOIN (SELECT Rtrim(Ltrim(Split.a.value('.', 'VARCHAR(100)'))) fs
FROM (SELECT Cast ('<M>' + Replace(#FileName, ',', '</M><M>')
+ '</M>' AS XML) AS Data) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)) ad
on Charindex(fs, a) > 0

Try this :
SELECT *
FROM JobAttachment a
JOIN (SELECT t1.nod.value('.', 'varchar(50)') tags
FROM (SELECT Cast('<N>.'
+ Replace(Replace(#FileName, '.', ''), ',', '</N><N>.')
+ '</N>' AS XML) AS format) t
CROSS APPLY format.nodes('/N') AS t1(nod)
WHERE t1.nod.value('.', 'varchar(50)') <> '.') fileformat
ON a.tag LIKE ( '%' + fileformat.tags + '%' )

You can create dynamic condition as
Declare #FileName nvarchar(60) = NULL
set #FileName = '.jpg,.Png,gif'
--append a comma to the string to get correct results with empty strings
--or strings with a single value (no commas)
SET #FileName = #FileName + ',';
declare #x XML
declare #FileSearch nvarchar(max)
select #x = cast( '<F>' + replace ( #FileName,',','</F><F>') + '</F>' as xml)
select #FileSearch = stuff( isnull(#FileSearch , '') +
' OR FileName Like ''%'+ isnull(t.value('.','nvarchar(60)'),'')
+'%''' ,1,3,'')
from #x.nodes('/F') as x(t)
And then create dynamic query to get desired results:
set #sql = 'select * from test where ' -- entire query goes here
+ #FileSearch
exec sp_executesql #sql
DEMO

Related

Select not null columns as a comma separated string from dynamic sql

I am trying to do my best to avoid using cursors. There is a comma separated list of columns in nvarchar variable that looks like this:
#columnList = 'col1,col2,col5'
There is a table with lots of varchar columns:
myTable: [col1],[col2],[col3],[col4],[col5],[col6],[col7]
This is how I select data using a dynamic sql:
exec ('select ' + #columnList + ' from myTable')
This query returns the following results:
[col1], [col2] , [col5]
null , "txt1" , null
"txt2", null , null
null , "txt3" , "txt4"
This is what I need to get:
#resultList = "txt1,txt2,txt3,txt4"
How do I select a comma separated string containing not-null values only? I know how to convert a table to comma separated string, so getting something like:
[column]
"txt1"
"txt2"
"txt3"
"txt4"
Is also fine. Any suggestions? Feel free to suggest a basic approach, I don't expect you to write the actual code for me.
You can use a solution like the following, using just a REPLACE to create the SQL query:
DECLARE #columnList VARCHAR(100)
SET #columnList = 'col1,col2,col5'
SET #columnList = REPLACE(#columnList, ',', ' AS colName FROM myTable UNION ALL SELECT ');
EXEC('SELECT * FROM (SELECT ' + #columnList + ' AS colName FROM myTable)t WHERE NOT t.colName IS NULL');
You can also use a solution using UNPIVOT:
DECLARE #columnList VARCHAR(100);
SET #columnList = 'col1,col2,col5';
EXEC('SELECT colName FROM (SELECT ' + #columnList + ' FROM myTable) t1 UNPIVOT (colName FOR columnNames IN (' + #columnList + ')) AS t2');
demo on dbfiddle.uk
Since you mention you already know how to aggregate into comma-seperated, here's how to unpivot your table with cross apply:
select unpivoted.*
from myTable
cross apply
( values
('col1',col2)
,('col2',col2)
,('col3',col3) -- etc
)unpivoted(colname,colval)
This would work for SQL Server 2017, on earlier version STRING_AGG usage should be replaced with XML-based solution.
You could first concatenate your results into a single line and then use STRING_AGG to aggregate them into a single string:
;with t as
(
SELECT * FROM (VALUES
(null , 'txt1' , null),
('txt2', null , null),
(null , 'txt3' , 'txt4')) x(col1, col2, col5)
)
SELECT STRING_AGG(STUFF(CONCAT(',' + col1, ',' + col2, ',' + col5), 1, 1, ''), ',')
FROM t
CTE is just for showcasing, you can simply do it in your dynamic query:
DECLARE #columnList NVARCHAR(MAX) = 'col1,col2,col5'
DECLARE #query NVARCHAR(MAX) = ''
SELECT #query = 'SELECT STRING_AGG(STUFF(CONCAT('','' + ' + REPLACE(#columnList, ',', ', '','' + ') + '), 1, 1, ''''), '','') from mytable'
EXEC sp_executesql #query
Working example on dbfiddle

Select distinct from temp table

I am trying to select distinct values from my temporary table column into varchar variable in sql server.
i tried following but it doesnt work.
DECLARE #GuidPrimaryTableSpace NVARCHAR(MAX);
SET #GuidPrimaryTableSpace = '';
SELECT DISTINCT
#GuidPrimaryTableSpace = #GuidPrimaryTableSpace+DeleteGuidStatement+';'+CHAR(13)+CHAR(10)
FROM ##Purge_GuidForeignKeyTablePurgeStatements;
Please Help!
I would recommend using the XML approach for string concatenation:
SELECT #GuidPrimaryTableSpace =
STUFF((SELECT DISTINCT ';' + CHAR(13) + CHAR(10) + DeleteGuidStatement
FROM ##Purge_GuidForeignKeyTablePurgeStatements
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)'
), 1, 3, ''
)
FROM ##Purge_GuidForeignKeyTablePurgeStatements;
You can use your method if you use a subquery:
DECLARE #GuidPrimaryTableSpace NVARCHAR(MAX);
SET #GuidPrimaryTableSpace = '';
SELECT #GuidPrimaryTableSpace = #GuidPrimaryTableSpace + DeleteGuidStatement + ';' + CHAR(13) + CHAR(10)
FROM (SELECT DISTINCT DeleteGuidStatement
FROM ##Purge_GuidForeignKeyTablePurgeStatements
) t;

Return SELECT query result as a CSV string

I have the following Sql Server 2016 SELECT statement that returns only 1 row:
SELECT TOP 1 * FROM tempdb.dbo.IMTD
How can I concatenate the values as a comma delimited string? NOTE: the column names of this temporary table are unknown as they can variate.
Thank you.
Something like this perhaps:
-- Sample data
DECLARE #someTable TABLE (SomeID int identity, SomeTxt varchar(100));
INSERT #someTable VALUES ('row1'),('row2'),('row3');
-- Solution
SELECT ConcatinatedString =
STUFF
((
SELECT ','+SomeTxt
FROM #someTable
FOR XML PATH(''), TYPE
).value('.','varchar(100)'),1,1,'');
You can use Dynamic query as below:
DECLARE #COLS VARCHAR(MAX) = ''
SELECT #COLS = #COLS + ',' + COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#table[_]%' -- Dynamic Table (here, Temporary table)
DECLARE #COLNAMES VARCHAR(MAX) = REPLACE(STUFF(#COLS, 1, 1, ''), ',', '+ '','' +')
Declare #cmd varchar(max) = 'Select ' + #COLNAMES + ' as CSVCol from #table'
-- will generate
-- Select Column1+ ',' +Column2+ ',' +Column3 as CSVCol from #table
EXEC (#cmd)
Another solution you can try is this.
SELECT LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
If you only want one row keep that top 1 In there like
SELECT TOP 1
LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
The LTRIM and RTRIM will remove any white space and this should allow you to copy and paste the result set anywhere you may need it. You will need to do this for each columnname.
You can use the query below to get the column names from your temp table.
DECLARE #ColumnNames NVARCHAR(MAX)
SELECT
#ColumnNames= COALESCE(#ColumnNames +',','')+COLUMN_NAME
FROM
TempDB.INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = '#TempTableName'

Returning all child nodes as columns from XML in Sql Server

I am doing the following to select nodes from an XML string, the first part is just to show you what I'm selecting from.
The issue is I want to do this for various different XML columns and I'd like to not have to specify the node name for each column in my select, is there a way to select all nodes as columns automatically or even a cursor using count?
DECLARE #MyXML XML
SET #MyXML = (SELECT
CAST (
'<AllowAdd>N</AllowAdd>
<Allowed>NUMSEG</Allowed>
<AllSegmentsEqualValue>N</AllSegmentsEqualValue>
<ClusterLevelSA>Y</ClusterLevelSA>
<ClusterLevelPremium>Y</ClusterLevelPremium>
<AllowAssignedAndInTrust>N</AllowAssignedAndInTrust>
<MinSegments>1</MinSegments>
<MaxSegments>100</MaxSegments>
<DefaultSegments>10</DefaultSegments>
<RoundPremiumsTo>2</RoundPremiumsTo>
<TaxDeferredAllowance>0.05</TaxDeferredAllowance>
<HigherTaxValueBands>HTVB</HigherTaxValueBands>
<NumberYearsCalculationType>NONFIN</NumberYearsCalculationType>
<OnShore>POLICY</OnShore>
<OffShore>NONFIN</OffShore>'as XML) as x)
SELECT
Data.Col.value('(/AllowAdd)[1]','Varchar(10)') as [Allow Addition of]
,Data.Col.value('(/Allowed)[1]','Varchar(10)') as [Allowed]
,Data.Col.value('(/MinSegments)[1]','Int') as [Min Segments]
,Data.Col.value('(/MaxSegments)[1]','Int') as [Max Segments]
,Data.Col.value('(/DefaultSegments)[1]','Int') as [Default Segments]
,Data.Col.value('(/RoundPremiumsTo)[1]','Int') as [Round Premiums To]
,Data.Col.value('(/AllSegmentsEqualValue)[1]','Varchar(10)') as [All Segments Equal Value]
--,Data.Col.value('(/TaxDeferredAllowance)[1]','Varchar(10)') as [Tax Deferred Allowance]
,Data.Col.value('(/HigherTaxValueBands)[1]','Varchar(10)') as [Higher Tax Value Bands]
,Data.Col.value('(/NumberYearsCalculationType)[1]','Varchar(10)') as [Number Years Calculation Type]
,Data.Col.value('(/OnShore)[1]','Varchar(10)') as [OnShore]
,Data.Col.value('(/OffShore)[1]','Varchar(10)') as [OffShore]
FROM #MyXML.nodes('/OffShore') AS Data(Col)
I hope, this is what you are waiting for :)
DECLARE #MyXML XML
SET #MyXML = (SELECT
CAST (
'<AllowAdd>N</AllowAdd>
<Allowed>NUMSEG</Allowed>
<AllSegmentsEqualValue>N</AllSegmentsEqualValue>
<ClusterLevelSA>Y</ClusterLevelSA>
<ClusterLevelPremium>Y</ClusterLevelPremium>
<AllowAssignedAndInTrust>N</AllowAssignedAndInTrust>
<MinSegments>1</MinSegments>
<MaxSegments>100</MaxSegments>
<DefaultSegments>10</DefaultSegments>
<RoundPremiumsTo>2</RoundPremiumsTo>
<TaxDeferredAllowance>0.05</TaxDeferredAllowance>
<HigherTaxValueBands>HTVB</HigherTaxValueBands>
<NumberYearsCalculationType>NONFIN</NumberYearsCalculationType>
<OnShore>POLICY</OnShore>
<OffShore>NONFIN</OffShore>'as XML) as x)
DECLARE #Output nvarchar(max) = N''
DECLARE #PivotList nvarchar(max)
SELECT
#PivotList = COALESCE(#PivotList + ', ', N'') + N'[' + XC.value('local-name(.)', 'varchar(100)') + N']'
FROM
#MyXML.nodes('/*') AS XT(XC)
SET #Output = N'SELECT
'+#PivotList+N'
FROM
(
SELECT
ColName = XC.value(''local-name(.)'', ''nvarchar(100)''),
ColValue = ISNULL(NULLIF(CONVERT(nvarchar(max),XC.query(''./*'')),''''),XC.value(''.'',''nvarchar(max)''))
FROM
#MyXML.nodes(''/*'') AS XT(XC)
) AS s
PIVOT
(
MAX(ColValue)
FOR ColName IN ('+#PivotList+N')
) AS t;'
EXEC sp_executesql #Output, N'#MyXml xml', #MyXML = #MyXML;
Given your input XML, you can try to use this:
SELECT
ColName = XC.value('local-name(.)', 'varchar(100)'),
ColValue = xc.value('(.)[1]', 'varchar(100)')
FROM
#MyXML.nodes('/*') AS XT(XC)
This will output each XML element found under the root - its name and value - as a list:
Of course, since it's a very generic approach, you cannot really define the proper datatypes for each columns in the second xc.value() - you basically get everything as a string.
Using a cursor to build a SELECT statement and sp_executesql to execute it!
DECLARE #MyXML XML
DECLARE #FieldName VARCHAR(MAX)
DECLARE #SELECT_TEXT NVARCHAR(MAX)
SET #MyXML = (SELECT
CAST (
'<AllowAdd>N</AllowAdd>
<Allowed>NUMSEG</Allowed>
<AllSegmentsEqualValue>N</AllSegmentsEqualValue>
<ClusterLevelSA>Y</ClusterLevelSA>
<ClusterLevelPremium>Y</ClusterLevelPremium>
<AllowAssignedAndInTrust>N</AllowAssignedAndInTrust>
<MinSegments>1</MinSegments>
<MaxSegments>100</MaxSegments>
<DefaultSegments>10</DefaultSegments>
<RoundPremiumsTo>2</RoundPremiumsTo>
<TaxDeferredAllowance>0.05</TaxDeferredAllowance>
<HigherTaxValueBands>HTVB</HigherTaxValueBands>
<NumberYearsCalculationType>NONFIN</NumberYearsCalculationType>
<OnShore>POLICY</OnShore>
<OffShore>NONFIN</OffShore>
'
as XML) as x)
SET #SELECT_TEXT = 'SELECT '
DECLARE xml_cursor CURSOR
FOR SELECT Data.Col.value( 'fn:local-name(.)', 'VARCHAR(MAX)' ) FROM #MyXML.nodes('/*') AS Data(Col)
open xml_cursor
While 1 = 1
BEGIN
fetch next from xml_cursor into #FieldName
if ##fetch_status <> 0
begin
break
end
SET #SELECT_TEXT = #SELECT_TEXT + 'Data.Col.value(''(/' + #FieldName + ')[1]'',''Varchar(MAX)'') as [' + #FieldName + ']' + ', '
END
close xml_cursor
deallocate xml_cursor
SET #SELECT_TEXT = SUBSTRING( #SELECT_TEXT,0, LEN(#SELECT_TEXT) ) + 'FROM #MyXML.nodes(''/OffShore'') AS Data(Col)'
EXECUTE sp_executesql #SELECT_TEXT, N'#MyXML XML', #MyXML = #MyXML
As previously mentioned in another comment the drawback is not having column types but it's for a report style query so strings is ok.

SQL create distinct comma separated lists

I have a stored procedures that accepts a comma separated list, then makes copies of that list with quoted strings and brackets, then uses those in a dynamic sql statement to build a pivot table with flexible number of columns.
My problem is that sometimes my users submit a list with duplicates, and that makes the pivot query fail. So I want to somehow select distinct from my comma separated strings.
Here's how I manipulate the initial string:
Declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
Declare #bracketed varchar(max) = ''
Declare #quoted varchar(max) = ''
select #bracketed = #bracketed + quotename(rtrim(ltrim(Value))) + ', ',
#quoted = #quoted + quotename(rtrim(ltrim(Value)), '''') + ', '
from [dbo].[fnSplitStringAsTable](#data, ',')
Select #bracketed = LEFT(#bracketed, len(#bracketed) - 1),
#quoted = LEFT(#quoted, len(#quoted) - 1)
I'm thinking I should be able to add DISTINCT somewhere in this query,
but I can't make it work. How can I select distinct from comma separated lists?
as an alternative solution you can dedupe in xml and convert back to varchar
Declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
set #data= (select '''' + cast(cast('<d>'+replace(#data, ', ',',</d><d>')+'</d>' as xml).query('distinct-values(/d)') as varchar) +'''')
select #data
I guess we can add in distinct after you make the table, like this:
select #bracketed = #bracketed + quotename(rtrim(ltrim(Value))) + ', ',
#quoted = #quoted + quotename(rtrim(ltrim(Value)), '''') + ', '
from (
SELECT DISTINCT Value FROM [dbo].[fnSplitStringAsTable](#data, ',')
) T
If this fails try this:
select #bracketed = #bracketed + quotename(Value) + ', ',
#quoted = #quoted + quotename(Value), '''') + ', '
from (
SELECT DISTINCT RTRIM(LTRIM(Value)) AS Value FROM [dbo].[fnSplitStringAsTable](#data, ',')
) T
With a little dynamic sql, you can select distinct values from your string variable into a table variable, and then put those values back into the original variable:
declare #data varchar(max) = '150593, 150593, 150603, 150578, 150604'
declare #table table(data varchar(10))
set #data = 'select distinct value from (values (''' +
replace(#data,', ','''),(''') + ''')) as v(value)'
insert into #table
exec(#data)
set #data = ''
select #data = #data + data +
case row_number() over(order by data desc)
when 1 then ''
else ','
end
from #table
order by data asc
select #data