Using Like in a Sub Query - subquery

Using Like in a Sub Query
Table A
Part Description
--------------------
Part1 Top Cover
Part2 Botom Cover
Part3 xxxx
Part4 Cover
Part5 yyyy
Table B
Keyword
-----------
Cover
Result should be
Part Description
--------------------
Part1 Top Cover
Part2 Botom Cover
Part4 Cover
I want to know the part in table a which has description as COVER
I used the following query
SELECT Part FROM TableA WHERE Description LIKE '%' + (SELECT Keyword FROM TableB ) + '%'

so you want to match all keywords from tableB. Cross-join is good choice here. Instead of sub query use join
select part
from tableA,
tableB
where Description LIKE '%Keyword%'

Related

SQL Server: use all the words of a string as separate LIKE parameters (and all words should match)

I have a string containing a certain number of words (it may vary from 1 to many) and I need to find the records of a table which contains ALL those words in any order.
For instances, suppose that my input string is 'yellow blue red' and I have a table with the following records:
1 yellow brown white
2 red blue yellow
3 black blue red
The query should return the record 2.
I know that the basic approach should be something similar to this:
select * from mytable where colors like '%yellow%' and colors like '%blue%' and colors like '%red%'
However I am not being able to figure out how turn the words of the string into separate like parameters.
I have this code that splits the words of the string into a table, but now I am stuck:
DECLARE #mystring varchar(max) = 'yellow blue red';
DECLARE #terms TABLE (term varchar(max));
INSERT INTO #terms
SELECT Split.a.value('.', 'NVARCHAR(MAX)') term FROM (SELECT CAST('<X>'+REPLACE(#mystring, ' ', '</X><X>')+'</X>' AS XML) AS String) AS A CROSS APPLY String.nodes('/X') AS Split(a)
SELECT * FROM #terms
Any idea?
First, put that XML junk in a function:
CREATE FUNCTION dbo.SplitThem
(
#List NVARCHAR(MAX),
#Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN ( SELECT Item = y.i.value(N'(./text())[1]', N'nvarchar(4000)')
FROM ( SELECT x = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i));
Now you can extract the words in the table, join them to the words in the input string, and discard any that don't have the same count:
DECLARE #mystring varchar(max) = 'red yellow blue';
;WITH src AS
(
SELECT t.id, t.colors, fc = f.c, tc = COUNT(t.id)
FROM dbo.mytable AS t
CROSS APPLY dbo.SplitThem(t.colors, ' ') AS s
INNER JOIN (SELECT Item, c = COUNT(*) OVER()
FROM dbo.SplitThem(#mystring, ' ')) AS f
ON s.Item = f.Item
GROUP BY t.id, t.colors, f.c
)
SELECT * FROM src
WHERE fc = tc;
Output:
id
colors
fc
tc
2
red blue yellow
3
3
Example db<>fiddle
This disregards any possibility of duplicates on either side and ignores the larger overarching issue that this is the least optimal way possible to store sets of things. You have a relational database, use it! Surely you don't think the tags on this question are stored somewhere as the literal string
string sql-server-2012 sql-like
Of course not, these question:tag relationships are stored in a, well, relational table. Splitting strings is for the birds and those with all kinds of CPU and time to spare.
If you are storing a delimited list in a single column then you really need to normalize it out into a separate table.
But assuming you actually want to just do multiple free-form LIKE comparisons, you can do them against a list of values:
select *
from mytable t
where not exists (select 1
from (values
('%yellow%'),
('%blue%'),
('%red%')
) v(search)
where t.colors not like v.search
);
Ideally you should pass these values through as a Table Valued Parameter, then you just put that into your query
select *
from mytable t
where not exists (select 1
from #tmp v
where t.colors not like v.search
);
If you want to simulate an OR semantic rather than AND the change not exists to exists and not like to like.

Python SQLite 3 query multiple query

I've a problem to in building a query for Python SQLite3 to do the following:
Count a word which appears in columns, if word appears more than 1 time count one.
I've attached a picture to illustrate my table format.
I tried this but the result still counts duplicate values with same ID.
"SELECT id, value, count(value) FROM table WHERE type like'%hi%' GROUP BY value ORDER BY COUNT(*)<1 DESC"
The result needs to be like:
Hi all you need can be achieved with GROUP BY clause.
This should help:
SELECT
id
,value
,1 AS cnt
FROM table
GROUP BY id, value
ORDER BY id
What you're looking for is DISTINCT clause or GROUP BY as mentioned by Peter.
for GROUP BY use this syntax:
SELECT
id
,value
,1 AS cnt
FROM table
GROUP BY id, value
for DISTINCT use this one:
SELECT DISTINCT
id
,value
,1 AS cnt
FROM table

SQL Server PIVOT - Vertical to Horizontal - error

Will you please help to check this?
CREATE TABLE Sales
(
Category NVARCHAR(30),
Region NVARCHAR(30),
Amount MONEY
)
DELETE FROM Sales
INSERT INTO Sales
VALUES
('X','1',24),
('X','2',NULL),
('X','3',165),
('X','4',36),
('Y','1',38),
('Y','2',181),
('Y','3',287),
('Y','4',NULL),
('Z','1',83),
('Z','2',55),
('Z','3',33),
('Z','4',44)
DECLARE #SQLStr NVARCHAR(MAX)
SELECT #SQLStr = COALESCE(#SQLStr + ',' ,'')+ [a].[Column]
FROM (SELECT DISTINCT Region AS [Column]
FROM Sales) AS a
SET #SQLStr = 'SELECT Category, ' + #SQLStr + ' FROM (SELECT Category, Region, Amount FROM Sales) sq '
+ ' PIVOT (SUM(Amount) FOR Region IN (' + #SQLStr + ')) AS pt'
PRINT #SQLStr
EXEC sp_executesql #SQLStr
I get an error
Msg 102, Level 15, State 1, Line 35
Incorrect syntax near '1'.
Initially, the column 'Region' is INT type (values are 1, 2, 3, 4)
The same error, then I change its type to NVARCHAR(30), but the same error happens. Please help.
In reality, I want to transpose the vertical product usage data to horizontal.
Please see the image link
Please see this screen shot, this is what I really want to achieve
As you see, the date is transposed to horizontal. I want to populate the usage data to horizontal way for my analysis. Please help
The column header can be date? or have to be string?
please add brackets with column name like below
DECLARE #SQLStr NVARCHAR(MAX)
SELECT #SQLStr = COALESCE(#SQLStr + ',' ,'')+ +'['+[a].[Column]+']'
FROM (SELECT DISTINCT Region AS [Column]
FROM #Sales) AS a
You should always place square brackets around the column names []:
From MSDN:
The first character must be one of the following:
A letter as defined by the Unicode Standard 3.2. The Unicode definition of letters includes Latin characters from a through z, from A through Z, and also letter characters from other languages.
The underscore (_), at sign (#), or number sign (#).
If it is anything else, then you will need to use the square brackets. []

USe Subquery to return columns from different tables

I want a sub query which returns columns from different tables
for example
i am writing the code in the way similar to below
Use North Wind Select *,(Select Order Id FROM dbo. Orders OI WHERE
OI.OrderID IN (Select OI.OrderID FROM [dbo].[Order Details] OD WHERE
OD.UnitPrice=P.UnitPrice))AS 'ColumName' FROM Products P
ERROR : Msg 512, Level 16, State 1, Line 1 Sub query returned more
than 1 value. This is not permitted when the subquery follows =, !=,
<, <= , >, >= or when the subquery is used as an expression.
Whats the Mistake in this code
please reply soon
Saradhi
Select Order Id FROM dbo. Orders OI WHERE OI.OrderID IN (Select OI.OrderID FROM [dbo].[Order Details] OD WHERE OD.UnitPrice=P.UnitPrice)
This query is returning more than one OrderId while it should be returning only one. See if your data is correct.

How to order results based on number of search term matches?

I am using the following InnoDB tables in mysql to describe records that can have multiple searchtags associated with them:
TABLE records
ID
title
desc
TABLE searchTags
ID
name
TABLE recordSearchTags
recordID
searchTagID
To SELECT records based on arbitrary search input, I have a statement that looks sort of like this:
SELECT
recordSearchTags.recordID
FROM
recordSearchTags
LEFT JOIN searchTags
ON recordSearchTags.searchTagID = searchTags.ID
WHERE
searchTags.name LIKE CONCAT('%','$search1','%') OR
searchTags.name LIKE CONCAT('%','$search2','%') OR
searchTags.name LIKE CONCAT('%','$search3','%') OR
searchTags.name LIKE CONCAT('%','$search4','%');
I'd like to ORDER this resultset, so that rows that match with more search terms are displayed in front of rows that match with fewer search terms.
For example, if a row matches all 4 search terms, it will be top of the list. A row that matches only 2 search terms will be somewhere in the middle. And a row that matches just one search term will be at the end.
Any suggestions on what is the best way to do this?
Thanks!
* Replaced answer, since fulltext isn't an option
Alright, it's not pretty, but you should be able to do something like this:
ORDER BY (searchTags.name LIKE CONCAT('%','$search1','%')
+ searchTags.name LIKE CONCAT('%','$search2','%')
+ searchTags.name LIKE CONCAT('%','$search3','%')
+ searchTags.name LIKE CONCAT('%','$search4','%'))
DESC;
LIKE returns 1 on a match or 0 if there is no match, so you should just be able to add the results together.
This isn't very pretty but one way would be to union the 4 likes in 4 statements like
select ... where searchTags.name LIKE CONCAT('%','$search1','%')
union
select ...
and so on. Wrap that in a:
select recordSearchTags.recordID, count(*) from (<inner unions>)
group by recordSearchTags.recordID
order by count(*)

Resources