sql like clause multiple values - sql

I have a table with multiple words, from 1 to n.
declare #words table
(
word varchar(100) not null
)
insert into #words (word) values ('word1')
insert into #words (word) values ('word2')
insert into #words (word) values ('word3')
declare #tablea table
(
column1 varchar(100) not null
)
insert into #tablea (column1) values ('aword1a aword2a aword3a')
insert into #tablea (column1) values ('word2a')
insert into #tablea (column1) values ('word3a')
Im having trouble to write a query to select from a table where a column is like these words, and I need the AND operator. If the table contains word1, word2, word3, the like clause must match the three words, it means, I want to return the first row in tablea.
select *
from tablea
where
column1 like ?

Updated:
select t.column1
from #tablea t
inner join #words w on charindex(w.word, t.column1) > 0
group by t.column1
having count(distinct w.word) = (select count(*) from #words)

Since any one column needs to contain all the values in the #words table, I would use a not exists, and try to find a value in #words that isn't contained in the column1 field.
select
*
from
#tablea a
where not exists (
select 1
from #words w
where a.column1 not like '%' + w.word + '%'
)

This will do it, but I'm not sure how extensible it is:
SELECT column1
FROM #tablea t
JOIN #words w ON t.column1 LIKE '%'+w.word+'%'
GROUP BY column1
HAVING COUNT(*) = (SELECT COUNT(*) FROM #words)
In the long run, you may be better off implementing Full Text Search.

Related

Insert multiple rows in a single query using results of a select statement

I am looking for a compact way to do this - insert multiple rows into a table with values from multiple columns of a row from another table. My destination table is really a list with a single column:
declare #stringList table
(
val nvarchar(100)
)
This is how we can insert multiple rows:
INSERT INTO #stringList ( val ) VALUES
Val1, Val2, Val3, ...
This is how we insert from a select:
INSERT INTO #stringList
SELECT col1 FROM table1 where id=something
But I cannot seem to find a way to use both at the same time.
I can select from one column:
insert into #stringList (val)
select col1 from table1 where id=something
But it doesn't extend to multiple columns:
insert into #stringList (val)
select col1, col2 from table1 where id=something
--The select list for the INSERT statement contains more items than the insert list. The number of SELECT values must match the number of INSERT columns.
I have tried various ways including using parentheses, but the syntax is not accepted:
insert into #stringList (val)
(select col1 from table1 where id=something,
select col2 from table1 where id=something
Any idea if what I want is doable?
You can unpivot using cross apply:
insert into #stringList (val)
select v.col
from table1 t1 cross apply
(values (t1.col1), (t1.col2)) v(col)
where t1.id = something;

Add values of a column of one table as columns to another table

I am getting trouble in inserting values of a column from one table as columns in another table.
I am having Table A with some values in col1 :
And another Table B with columns equal to values of col1.
I want to add rest of the values from Table A, col1 as columns in Table B. Please help me out solving my problem. I am using SQL server 2012.
Create table tableA
(
Col1 varchar(50)
)
Create table tableB
(
Col1 varchar(50)
)
Insert into tableA values ('abc')
Insert into tableA values ('bbb')
Insert into tableA values ('ddd')
Insert into tableA values ('Col2')
Insert into tableA values ('Col3')
go
Declare #colName varchar(5000), #Text varchar(5000)
if EXISTS (select 1 from sys.tables where object_id=OBJECT_ID('tableB'))
BEGIN
SELECT #colName=ISNULL(#colName,'')+ (Col1) + ' varchar(50), ' FROM tableA WHERE Col1 not in (SELECT name FROM sys.columns WHERE object_id = OBJECT_ID('tableB'))
select #colName= SUBSTRING (#colName,0,LEN(#colName))
select #colName
SET #Text='ALTER table tableB Add '+#colName
END
ELSE
BEGIN
print 1
SELECT #colName=ISNULL(#colName,'')+ (Col1) + ' varchar(50), ' FROM tableA
group by Col1
select #colName= SUBSTRING (#colName,0,LEN(#colName))
select #colName
SET #Text = 'CREATE TABLE tableB ( '+#colName+' )'
END
select #Text
EXEC (#Text)
select * from tableA
select * from tableB

Sql insert multiple rows if not exists

I have a sql table that has two columns id and name. I have list of names about 20 and I need to write a query that checks if name exists before insert.
Is there a better way of doing this rather then just having the below query 20 times but with different names (I need do this in t-sql):
IF NOT EXISTS(SELECT*
FROM mytable
WHERE name = 'Dan')
BEGIN
INSERT INTO mytable
(name)
VALUES ('dan')
END
INSERT INTO MyTable (Name)
SELECT NewNames.Name
FROM ( VALUES ('Name1'), ('Name2'), ('Name3') ) AS NewNames (Name)
WHERE NOT EXISTS ( SELECT 1
FROM MyTable AS MT
WHERE MT.Name = NewNames.Name );
I think you could use a merge statement:
MERGE INTO myTable AS Target
USING (VALUES ('name1'),('name2'),('...')) AS source (NAME)
ON Target.NAME = Source.NAME
WHEN NOT MATCHED BY TARGET THEN
INSERT (NAME) VALUES (name)
You can filter values with NOT EXISTS
INSERT INTO myTable (
Name
)
SELECT DISTINCT
Name
FROM (
VALUES ('Name 1'),
('Name 2')
) AS NewNames(Name)
WHERE
NOT EXISTS (SELECT 1 FROM TargetTable WHERE myTable.Name = NewNames.Name)
If your new names are in another table, you can change the select query in the above one.
Please note, that the DISTINCT keyword is necessary to filter out the duplications in the source data.
I would do this using insert:
with names as (
select 'Dan' as name union all
select 'name2' union all
. . .
)
insert into myTable(name)
select distinct name
from myTable
where not exists (select 1 from mytable t2 where t2.name = t.name);
Note: you may want to create a unique index on mytable(name) so the database does the checking for duplicates.
untested so there might be some minor errors:
merge into mytable x
using (
values ('name1')
, ('name2')
, ...
, ('namen')
) as y (name)
on x.name = y.name
when not matched then
insert (name)
values (y.name)
INSERT INTO MyTable (Name)
SELECT Name FROM
(
VALUES ('Name 1'),
('Name 2')
) AS Names(Name)
WHERE Name NOT IN
(
SELECT Name FROM MyTable
)
INSERT IGNORE INTO myTable (column1, column2) VALUES (val1, val2),(val3,val4),(val5,val6);
INSERT IGNORE will allow skip on duplicate values

Select records with order of IN clause

I have
SELECT * FROM Table1 WHERE Col1 IN(4,2,6)
I want to select and return the records with the specified order which i indicate in the IN clause
(first display record with Col1=4, Col1=2, ...)
I can use
SELECT * FROM Table1 WHERE Col1 = 4
UNION ALL
SELECT * FROM Table1 WHERE Col1 = 6 , .....
but I don't want to use that, cause I want to use it as a stored procedure and not auto generated.
I know it's a bit late but the best way would be
SELECT *
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')
Or
SELECT CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')s_order,
*
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY s_order
You have a couple of options. Simplest may be to put the IN parameters (they are parameters, right) in a separate table in the order you receive them, and ORDER BY that table.
The solution is along this line:
SELECT * FROM Table1
WHERE Col1 IN(4,2,6)
ORDER BY
CASE Col1
WHEN 4 THEN 1
WHEN 2 THEN 2
WHEN 6 THEN 3
END
select top 0 0 'in', 0 'order' into #i
insert into #i values(4,1)
insert into #i values(2,2)
insert into #i values(6,3)
select t.* from Table1 t inner join #i i on t.[in]=t.[col1] order by i.[order]
Replace the IN values with a table, including a column for sort order to used in the query (and be sure to expose the sort order to the calling application):
WITH OtherTable (Col1, sort_seq)
AS
(
SELECT Col1, sort_seq
FROM (
VALUES (4, 1),
(2, 2),
(6, 3)
) AS OtherTable (Col1, sort_seq)
)
SELECT T1.Col1, O1.sort_seq
FROM Table1 AS T1
INNER JOIN OtherTable AS O1
ON T1.Col1 = O1.Col1
ORDER
BY sort_seq;
In your stored proc, rather than a CTE, split the values into table (a scratch base table, temp table, function that returns a table, etc) with the sort column populated as appropriate.
I have found another solution. It's similar to the answer from onedaywhen, but it's a little shorter.
SELECT sort.n, Table1.Col1
FROM (VALUES (4), (2), (6)) AS sort(n)
JOIN Table1
ON Table1.Col1 = sort.n
I am thinking about this problem two different ways because I can't decide if this is a programming problem or a data architecture problem. Check out the code below incorporating "famous" TV animals. Let's say that we are tracking dolphins, horses, bears, dogs and orangutans. We want to return only the horses, bears, and dogs in our query and we want bears to sort ahead of horses to sort ahead of dogs. I have a personal preference to look at this as an architecture problem, but can wrap my head around looking at it as a programming problem. Let me know if you have questions.
CREATE TABLE #AnimalType (
AnimalTypeId INT NOT NULL PRIMARY KEY
, AnimalType VARCHAR(50) NOT NULL
, SortOrder INT NOT NULL)
INSERT INTO #AnimalType VALUES (1,'Dolphin',5)
INSERT INTO #AnimalType VALUES (2,'Horse',2)
INSERT INTO #AnimalType VALUES (3,'Bear',1)
INSERT INTO #AnimalType VALUES (4,'Dog',4)
INSERT INTO #AnimalType VALUES (5,'Orangutan',3)
CREATE TABLE #Actor (
ActorId INT NOT NULL PRIMARY KEY
, ActorName VARCHAR(50) NOT NULL
, AnimalTypeId INT NOT NULL)
INSERT INTO #Actor VALUES (1,'Benji',4)
INSERT INTO #Actor VALUES (2,'Lassie',4)
INSERT INTO #Actor VALUES (3,'Rin Tin Tin',4)
INSERT INTO #Actor VALUES (4,'Gentle Ben',3)
INSERT INTO #Actor VALUES (5,'Trigger',2)
INSERT INTO #Actor VALUES (6,'Flipper',1)
INSERT INTO #Actor VALUES (7,'CJ',5)
INSERT INTO #Actor VALUES (8,'Mr. Ed',2)
INSERT INTO #Actor VALUES (9,'Tiger',4)
/* If you believe this is a programming problem then this code works */
SELECT *
FROM #Actor a
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY case when a.AnimalTypeId = 3 then 1
when a.AnimalTypeId = 2 then 2
when a.AnimalTypeId = 4 then 3 end
/* If you believe that this is a data architecture problem then this code works */
SELECT *
FROM #Actor a
JOIN #AnimalType at ON a.AnimalTypeId = at.AnimalTypeId
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY at.SortOrder
DROP TABLE #Actor
DROP TABLE #AnimalType
ORDER BY CHARINDEX(','+convert(varchar,status)+',' ,
',rejected,active,submitted,approved,')
Just put a comma before and after a string in which you are finding the substring index or you can say that second parameter.
And first parameter of CHARINDEX is also surrounded by , (comma).

Query SQL with like operator from two tables

How can I do a SQL query with the like operator from two different tables?
I need something like:
select * from table1 where name like %table2.name
It's not a common field but a substring of a field on another table.
Edit
(original answer is further down)
Your comment (and subsequent edit) completely changes the question.
To do that, you can use LIKE as part of the ON clause in a join:
CREATE TABLE a (foo varchar(254))
GO
CREATE TABLE b (id int, bar varchar(254))
GO
INSERT INTO a (foo) VALUES ('one')
INSERT INTO a (foo) VALUES ('tone')
INSERT INTO a (foo) VALUES ('phone')
INSERT INTO a (foo) VALUES ('two')
INSERT INTO a (foo) VALUES ('three')
INSERT INTO b (id, bar) VALUES (2, 'ne')
INSERT INTO b (id, bar) VALUES (3, 't')
SELECT a.foo
FROM a
INNER JOIN b ON a.foo LIKE '%' + b.bar
WHERE b.id = 2
(That's the SQL Server version; for MySQL, add in the various semicolons, remove the GOs, and use ...LIKE concat('%', b.bar) instead.)
That uses id = 2 to find bar = "ne" in table b, then prepends the % operator and uses it to filter results from a. Results are:
one
tone
phone
You won't have to do the concat if you can store the operator in b.bar.
Separately, I was surprised to find that this works (on SQL Server) as well:
SELECT foo
FROM a
WHERE foo LIKE (
SELECT TOP 1 '%' + bar
FROM b
WHERE id = 2
)
...but the version using JOIN is probably more flexible.
That should get you going.
Original answer
(Arguably no longer relevant)
It's hard to tell what you're asking, but here's an example of using LIKE to limit the results from a JOIN:
SELECT a.foo, b.bar
FROM someTable a
INNER JOIN someOtherTable b
ON a.someField = b.someField
WHERE a.foo LIKE 'SOMETHING%'
AND b.bar LIKE '%SOMETHING ELSE'
That will give you foo from someTable and bar from someOtherTable where the rows are related by someField and foo starts with "SOMETHING" and bar ends with "SOMETHING ELSE".
Not particularly sure about the precise syntax, but here's an idea:
select ... from (
select ID, Foo as F from FooTable
union all
select ID, Bar as F from BarTable) R
where R.F like '%text%'
Based on #TJCrowder answer
Test Tables
create table #A (
id varchar(10)
)
create table #b(
number varchar(5)
)
insert into #A values('123')
insert into #A values('456')
insert into #A values('789')
insert into #A values('0123')
insert into #A values('4567')
select * from #A
insert into #B values('12')
insert into #b values('45')
insert into #b values('987')
insert into #b values('012')
insert into #b values('666')
Actual query
select * from #a, #b
where #a.id like '%' + #b.number + '%'
Modify the above query as you need such as
select #A.* from #A,#B ...
or
select * from #a, #b
where #a.id like #b.number + '%' -- one side match