How to create Dynamic SQL based on two tables - sql

I'm trying to construct a dynamic SQL based on the Cartesian product of two tables
Table1 Colunm1 Dev Test
table2 Column2 ProductNumber ProductDesc
here the result that I want:
(ProductNumber LIKE '%dev%' OR ProductDesc LIKE '%dev%' )
AND (ProductNumber LIKE '%Test%' OR ProductDesc LIKE '%Test%')
I tried to do some simple query like below but I cannot manage to add a AND instaed a OR between each column1 value
SELECT #sql = COALESCE(#sql + Colunm2 + ' LIKE ''%' + Colunm1 + '%'' OR ','')
from Table1, Table2
that give:
ProductNumber LIKE '%dev%' OR
ProductDesc LIKE '%dev%' OR
ProductNumber LIKE '%Test%' OR
ProductDesc LIKE '%Test%'
I can do it with a while but if you have a better solution I can use it

I note that you want your ORs grouped by table1.column1, so the below should work:
SELECT CASE WHEN row_num = 1 THEN ') AND (' ELSE '' END || code as code
FROM (
SELECT Column1, ROW_NUMBER() OVER (GROUP BY Column 1) as row_num, COALESCE( Column2 + ' LIKE ''%' + Column1 + '%'' OR ','') as code
FROM Table1, Table2
) gen_code
ORDER BY Column1, row_num
(I haven't tested it, but I have written lots of such code before)
It adds an additional ') AND (' at the beginning, but you can get it away if you use another ROW_NUMBER over the whole thing. It also lacks a closing ')', but you get the idea. Other than that, use your current approach with a variant of above code. Note that I assumed you have no string aggregation function available.

Related

How to retrieve the matched word Text Search

How to retrieve the word text search rows. For example, if I search input as 'water Bottel', I need an output like 'Water Soap Bottel','Water Milk Bottel','Water Copper Bottel'. I know how to use LIKE Operator.
IF OBJECT_ID('tempdb..#SearchText') IS NOT NULL
DROP TABLE #SearchText
CREATE TABLE #SearchText
(
ProductId INT,
ProductName VARCHAR(500)
)
INSERT INTO #SearchText VALUES
(1,'Water Soap Bottel'),
(2,'Water Milk Bottel'),
(3,'Wooden Box'),
(4,'Water Plastic Bottel'),
(5,'Water Copper Bottel')
You can do this:
DECLARE #SearchTerm VARCHAR(100) = 'water bottel'
SELECT *
FROM #SearchText
WHERE ProductName LIKE '%' + REPLACE(#SearchTerm, ' ', '%') + '%'
However if you need to also return a row containing the phrase bottel water, the order of those words will mean the above doesn't work. In that case you will need to break up the query into multiple words, for example:
SELECT *
FROM #SearchText
WHERE ProductName LIKE '%water%'
AND ProductName LIKE '%bottel%'
If you have a full text index on that table, you could use CONTAINS:
SELECT *
FROM #SearchText
WHERE CONTAINS(ProductName, '"water" AND "bottel"')
You can split data on space and search if the splitted word match the splitted productname :
If all searched word must matches :
SELECT *
FROM #SearchText st
WHERE ( SELECT COUNT(value)
FROM STRING_SPLIT('water Bottel', ' ') ) = ( SELECT COUNT(*)
FROM STRING_SPLIT(st.ProductName, ' ') AS sv
JOIN STRING_SPLIT('water Bottel', ' ') AS ss
ON sv.value = ss.value )
If one or more word must match:
SELECT *
FROM #SearchText st
WHERE EXISTS ( SELECT 1
FROM STRING_SPLIT(st.ProductName, ' ') AS sv
JOIN STRING_SPLIT('water Bottel', ' ') AS ss
ON sv.value = ss.value )
Note : The string_split function is built-in on SQL Server 2016, you can search a create a custom implementation if you use a lower version.
Use LIKE operator.
SELECT
*
FROM #SearchText
WHERE LOWER(ProductName) LIKE '%water%'
AND LOWER(ProductName) LIKE '%bottel%'
You can ommit LOWER(...) function if collaction of column/database/server is case insensitive.

MSSQL query search with keyword list

I got one table that contains all information about products. I need to list all articles with a matching keywords (in this case the brand name) in a specific column. Is it possible to initiate some kind of a 'list' with all brand names that I can use for this operation? chaning OR for all brands seems kinda bad.
In the second step I only need to see all articles that does not contain a specific word order before they keywords from the first step.
DECLARE #brand NVARCHAR =
'bmw, toyota, mercedes'
SELECT [Artikelnum]
FROM [dbo].[LAGER]
WHERE [XWebtexke] like '%' + #brand +'%' AND [XWebtexke] NOT LIKE '%suited for%'
GO
Thats what I got so far, but it does not work in the way I need it.
DECLARE #brand NVARCHAR =
'bmw, toyota, mercedes'
select * from (
SELECT [Artikelnum]
FROM [dbo].[LAGER]
WHERE [XWebtexke] NOT LIKE '%suited for%' )t4
WHERE [XWebtexke] like '%' + #brand +'%'
GO
DECLARE #brand NVARCHAR =
'bmw, toyota, mercedes'
select * from (
SELECT [Artikelnum]
FROM [dbo].[LAGER]
WHERE [XWebtexke] NOT LIKE '%suited for%' )t4
WHERE t4.[XWebtexke] like '%' + #brand +'%'
GO
Realized you need all the keywords to match. Here is the solution for that.
You need to split the brand variable, try this:
DECLARE #brand NVARCHAR(200) = 'bmw, toyota, mercedes'
;WITH CTE as
(
SELECT '%'+ t.c.value('.', 'VARCHAR(2000)')+'%' val
FROM (
SELECT x = CAST('<t>' +
REPLACE(#brand, ', ', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY x.nodes('/t') t(c)
)
SELECT [Artikelnum]
FROM [dbo].[LAGER]
WHERE
not exists(SELECT * FROM CTE WHERE [XWebtexke] not like val)
and [XWebtexke] NOT LIKE '%suited for%'
I am assuming there is always a space after the comma, you can adjust the code with ease if that is not always the case.
In sqlserver 2016 you can use STRING_SPLIT instead of the split used in my answer

SQL Select Statement LIKE IN

I need to write a select statement which returns a list of users where a list of SenderSubIDs exist in a field called constraint_values:
I need a LIKE IN statement ideally:
SELECT SenderSubID FROM fix_user_subids WHERE SenderSubID IN ('**00390529MGERAN1**','**00912220PBALDIS**','**03994113LDAMBRO**','**04004308SLOMBAR**','**04935278CARELLI**','**4004308SLOMBARD**')
SELECT * FROM fix_dyno_rule_defs WHERE constraint_values LIKE '%**00390529MGERAN1**%'
Returns:
rule_def_id tag msg_type required constraint_values constraint_type data_type default_value validation_type trans_type attribute_tag trans_tag memo
99800 10000 D,F,G 0 ((50,4,1,00390529MGERAN1)or(50,4,1,00912220PBALDIS)or(50,4,1,03994113LDAMBRO)or(50,4,1,04004308SLOMBAR)or(50,4,1,04935278CARELLI)or(50,4,1,4004308SLOMBARD))and(21,4,1,3)#STROP1#addattr(EQD,EQST) 0 1 #TAG=6506# 12 1800 0 0 Set EQD=1 for Equity Desk
I wrote this:
SELECT * FROM fix_dyno_rule_defs WHERE constraint_values LIKE '%' + (SELECT MAX(SenderSubID) FROM fix_user_subids WHERE SenderSubID IN ('00390529MGERAN1','00912220PBALDIS','03994113LDAMBRO','04004308SLOMBAR','04935278CARELLI','4004308SLOMBARD')) +'%'
But need it without the MAX as there is a list...
You don't get your ideal. Use or:
SELECT SenderSubID
FROM fix_user_subid
WHERE SenderSubID like '%00390529MGERAN1%' OR
SenderSubID like '%00912220PBALDIS%' OR
SenderSubID like '%04004308SLOMBAR%' OR
SenderSubID like '%04935278CARELLI%' OR
SenderSubID like '%4004308SLOMBARD%'
/This should help you try this
declare a temp table and store all the IDs in it/
declare #tempSenderIDs Table(
T_TableID varchar(10)
)
insert into #tempSender
(
T_TableID
)
values
select
senderSubID
from
SenderSubIDs
/final result will come from here/
select
f.SenderSubIDs
from
fix_user_subid f
where
s.ConstraintValue like '%' + (select T_TableID from #tempSenderIDs) +'%'
If I'm reading your question right (and I might not be!) you're looking to get results from the table fix_dyno_rule_defs.
In which case, can't you just do a simple join?
ie:
SELECT DISTINCT fdrd.*
FROM fix_dyno_rule_defs fdrd
JOIN fix_user_subid fus
ON fdrd.constraint_values LIKE '%' + REPLACE(fus.SenderSubID, '*','') + '%'
WHERE fus.SenderSubID IN ('**00390529MGERAN1**','**00912220PBALDIS**',
'**03994113LDAMBRO**','**04004308SLOMBAR**',
'**04935278CARELLI**','**4004308SLOMBARD**')

Query with LIKE statement for any of the words, not whole

SELECT *
FROM Products
WHERE Name LIKE '%' +
(SELECT TOP 1 Gift.Name FROM Gift WHERE Id = 65)
+ '%'
Subquery returns sth like "toy gun". Some of them even consists of three or more words. Obviously main query looks for Names that include "toy gun".
What I want to do is return all results for "toy" or "gun".
Any suggestion?
You will need to create function that splits out the text of your column. Here is one possible way to do it:
http://www.sqlservercentral.com/blogs/querying-microsoft-sql-server/2013/09/19/how-to-split-a-string-by-delimited-char-in-sql-server/
Once you have that, you can use a JOIN with a LIKE:
SELECT
*
FROM
Products p
INNER JOIN dbo.fnSplitString
(
SELECT TOP 1 Gift.Name FROM Gift WHERE Id = 65
) sub ON p.Name LIKE '%' + sub.splitdata + '%'
(I'm sure that's not 100% correct syntax.)
If you have Full Text indexing enabled then using FREETEXT query produce what you want. You can check Full Text if it enabled by running the below query:
SELECT FULLTEXTSERVICEPROPERTY('IsFullTextInstalled')
If the above returns 1, then your good to go. If 0 is returned then search for installation instructions for your SQL Server version. Here is a good guide to setting up the FullText index http://blog.sqlauthority.com/2008/09/05/sql-server-creating-full-text-catalog-and-index/.
Once set up you can use the below code to perform your required search:
Declare #searchString nvarchar (100);
Select top 1 #searchString = Gift.Name FROM Gift WHERE Id=65;
Select * From Products Where FREETEXT (Name, #searchString);
declare #query varchar(8000)
select #query='
SELECT *
FROM Products
WHERE Name LIKE ''%' +
replace((SELECT TOP 1 Gift.name FROM Gift),' ','%'' or name like ''%')
+ '%'''
exec (#query)
Use a split function on Gift.name, to generate a table of single-word names, and link to that table on Product.Name LIKE '%'+SplitFunctionTable.Name+'%'.
If you don't already have a split function in your database, Google can show you some.
This chops a string of two words delimited by one space into single words
declare #s nvarchar (30)='toy gun'
select LTRIM(SUBSTRING(#s, CHARINDEX(' ',#s)+1,len(#s)))
select LTRIM(SUBSTRING(#s, 0,CHARINDEX(' ',#s)+1))
Maybe this helps. Looks ugly though from any angle...
SELECT *
FROM Products
WHERE Name LIKE '%' +
(SELECT TOP 1 Gift.Name FROM Gift WHERE Id = 65)
+ '%'
I'm not sure if that's what you want, but if you don't want to create function.
SELECT *
FROM Products
WHERE ' ' + (SELECT TOP 1 Gift.Name FROM Gift WHERE Id = 65) + ' '
LIKE '%' + ' ' + REPLACE(REPLACE(REPLACE(
Name,'[','[[]'), '_', '[_]'), '%', '[%]') + ' ' + '%'
.
Gift.Name Products.Name
' toy gun ' LIKE '% toy %' true
' toy gun ' LIKE '% gun %' true
' toy gun ' LIKE '% toy gun %' true
' toy gun ' LIKE '% guns %' false
' toy gun ' LIKE '% gu %' false
' toy gun ' LIKE '% to %' false
' toy gun ' LIKE '% toys %' false
' toy gun ' LIKE '% gun toy %' false

a sql query with multiple search word

i use following query to get all data which contains the some words (which is split by a function) in the name column of the inventoryLocalization table.
in the example i have split "red green blue" string.
as it should be, it returned all rows like OR operator.
SELECT distinct
inL.name
FROM dbo.[inventoryLocalization] inL
JOIN fnSplitString (N'red green blue',' ' ) words ON (inL.name LIKE '%'+ words.item +'%')
My question is, is it possible to get rows which has all words, as in the AND operator.
select inL.name from dbo.[inventoryLocalization] inL
where not exists
(select 1 from fnSplitString(N'red green blue',' ') words
where (inL.name NOT LIKE '%'+ words.item +'%'))
Try something like this:
DECLARE #SomeWords NVARCHAR(200), #Num INT
SET #SomeWords = 'red green blue'
SELECT #Num = COUNT(*)
FROM fnSplitString (#SomeWords,' ')
SELECT inL.name
FROM dbo.[inventoryLocalization] inL
JOIN fnSplitString (#SomeWords,' ' )words
ON (inL.name LIKE '%'+ words.item +'%')
GROUP BY inL.name
HAVING COUNT(*) = #Num