51

Since I believe this should be a basic question I know this question has probably been asked, but I am unable to find it. I'm probably about to earn my Peer Pressure badge, but I'll ask anyway:

Is there a way in SQL Server that I am not aware of for using the wildcard character % when using IN.

I realize that I can use OR's like:

select *
from jobdetails
where job_no like '0711%' or job_no like '0712%'

and in some cases I can use a subquery like:

select *
from jobdetails
where job_no in (select job_no from jobs where job_id = 39)

but I'm looking to do something like the following:

select *
from jobdetails
where job_no in ('0711%', '0712%')

In this case it uses the percent sign as a character instead of a wildcard character so no rows are returned. I currently just use a bunch of OR's when I have to do this, but I know there has to be a better way. What method do you use for this?

raven
  • 18,004
  • 16
  • 81
  • 112
Dusty
  • 4,667
  • 3
  • 29
  • 35

16 Answers16

29

How about:

WHERE LEFT(job_no, 4) IN ('0711', '0712', ...)
Aaron Alton
  • 22,728
  • 6
  • 34
  • 32
  • 8
    I appreciate your response though and yes this works, but this is probably due to the simplifying of my example. I'd like something that didn't necessarily rely on the first 4 characters. I'm looking for something that would rely more on the wildcard. Thanks again though. – Dusty Jul 02 '09 at 19:13
  • 1
    This appears to be the best answer so far, at least in my case. this will match any values starting with the specified text in the list, and makes it much easier to add entries (I need a list of 100 entries, so most of the other solutions are too verbose) – Gavin Coates Apr 04 '12 at 15:32
16

I think I have a solution to what the originator of this inquiry wanted in simple form. It works for me and actually it is the reason I came on here to begin with. I believe just using parentheses around the column like '%text%' in combination with ORs will do it.

select * from tableName
where (sameColumnName like '%findThis%' or sameColumnName like '%andThis%' or 
sameColumnName like '%thisToo%' or sameColumnName like '%andOneMore%') 
TylerH
  • 20,799
  • 66
  • 75
  • 101
notYetExpert
  • 161
  • 1
  • 2
11

How about something like this?

declare @search table
(
    searchString varchar(10)
)

-- add whatever criteria you want...
insert into @search select '0711%' union select '0712%'

select j.*
from jobdetails j
    join @search s on j.job_no like s.searchString
GalacticCowboy
  • 11,663
  • 2
  • 41
  • 66
  • 1
    And, as in AlexKuznetsov's answer, you can also do it in one query without the table variable or temp table. – GalacticCowboy Jul 02 '09 at 19:34
  • This is an interesting approach that I hadn't thought of. It probably runs faster than a bunch of OR's, but it'd probably be faster typing (copy and pasting) the OR's. I generally only do it if I need an ad hoc report for someone so generally the reason I want to do this is to save typing time. – Dusty Jul 02 '09 at 20:33
  • better that first comment had a link to the answer instead of a (no much much later) reference that has changed over time – Mark Schultheiss Oct 08 '19 at 11:23
8

You could try something like this:

select *
from jobdetails
where job_no like '071[12]%'

Not exactly what you're asking, but it has the same effect, and is flexible in other ways too :)

Jeremy Smyth
  • 23,270
  • 2
  • 52
  • 65
  • This is pretty close to what I was looking for. Can the values between the quotes be expanded to for multiple values (Ex '071[10,22]%') and do you have a link that explains this in detail? – Dusty Jul 02 '09 at 20:27
  • 1
    @Dusty: No, '071[10,22]% will match any string '071x%, where x is one of 1 0 , or 2. Not looking for a 071 followed by either 10 or 22. See the patern section at: http://msdn.microsoft.com/en-us/library/ms179859.aspx – Shannon Severance Jul 02 '09 at 21:13
  • +1 although this is not exactly what I am looking for, but it is close and is helpful. Though it is probably the closest to what I was looking for I can't exactly mark it as the answer. Thanks – Dusty Jul 02 '09 at 21:39
  • HaHa, Sorry man. I'm going to post a follow-up question shortly that defines the issue which led me to this question. I figured if I could answer this question my problem would be resolved. Thanks again man for your response though. – Dusty Jul 02 '09 at 21:57
4
SELECT c.* FROM(
SELECT '071235' AS token UNION ALL SELECT '07113' 
 UNION ALL SELECT '071343'
UNION ALL SELECT '0713SA'
UNION ALL SELECT '071443') AS c
JOIN (
SELECT '0712%' AS pattern UNION ALL SELECT '0711%' 
 UNION ALL SELECT '071343') AS d
ON c.token LIKE d.pattern

071235
07113
071343
A-K
  • 16,804
  • 8
  • 54
  • 74
4

I had a similar goal - and came to this solution:

select *
from jobdetails as JD
where not exists ( select code from table_of_codes as TC 
                      where JD.job_no like TC.code ) 

I'm assuming that your various codes ('0711%', '0712%', etc), including the %, are stored in a table, which I'm calling *table_of_codes*, with field code.

If the % is not stored in the table of codes, just concatenate the '%'. For example:

select *
from jobdetails as JD
where not exists ( select code from table_of_codes as TC 
                      where JD.job_no like concat(TC.code, '%') ) 

The concat() function may vary depending on the particular database, as far as I know.

I hope that it helps. I adapted it from:

http://us.generation-nt.com/answer/subquery-wildcards-help-199505721.html

Julian
  • 41
  • 1
3
  1. I firstly added one off static table with ALL possibilities of my wildcard results (this company has a 4 character nvarchar code as their localities and they wildcard their locals) i.e. they may have 456? which would give them 456[1] to 456[Z] i.e 0-9 & a-z

  2. I had to write a script to pull the current user (declare them) and pull the masks for the declared user.

  3. Create some temporary tables just basic ones to rank the row numbers for this current user

  4. loop through each result (YOUR Or this Or that etc...)

  5. Insert into the test Table.

Here is the script I used:

Drop Table #UserMasks 
Drop Table #TESTUserMasks 

Create Table #TESTUserMasks (
    [User] [Int] NOT NULL,
    [Mask] [Nvarchar](10) NOT NULL)

Create Table #UserMasks (
    [RN] [Int] NOT NULL,
    [Mask] [Nvarchar](10) NOT NULL)

DECLARE @User INT
SET @User = 74054

Insert Into #UserMasks 
select ROW_NUMBER() OVER ( PARTITION BY ProntoUserID ORDER BY Id DESC) AS RN,
       REPLACE(mask,'?','') Mask
from dbo.Access_Masks 
where prontouserid = @User

DECLARE @TopFlag INT
SET @TopFlag = 1

WHILE (@TopFlag <=(select COUNT(*) from #UserMasks))
BEGIN
    Insert Into #TestUserMasks 
    select (@User),Code from dbo.MaskArrayLookupTable 
    where code like (select Mask + '%' from #UserMasks Where RN = @TopFlag)

    SET @TopFlag = @TopFlag + 1
END
GO

select * from #TESTUserMasks
TylerH
  • 20,799
  • 66
  • 75
  • 101
Tim
  • 41
  • 2
1

The IN operator is nothing but a fancy OR of '=' comparisons. In fact it is so 'nothing but' that in SQL 2000 there was a stack overflow bug due to expansion of the IN into ORs when the list contained about 10k entries (yes, there are people writing 10k IN entries...). So you can't use any wildcard matching in it.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
1

As Jeremy Smith posted it, i'll recap, since I couldn't answer to that particular question of his.

select *
from jobdetails
where job_no like '071[1-2]%'

If you just need 0711% and 0712% you can also place a ranges within the brackets. For the NOT keyword you could also use [^1-2]%

Dan Mihalea
  • 164
  • 8
0

In Access SQL, I would use this. I'd imagine that SQLserver has the same syntax.

select * from jobdetails where job_no like "0711*" or job_no like "0712*"

PowerUser
  • 11,583
  • 20
  • 64
  • 98
  • I appreciate your response, but I'm trying to figure out a way to use the wildcard in an IN so that I don't have to do multiple OR's. – Dusty Jul 02 '09 at 20:35
0

A bit late to the party, but you could use STRING_SPLIT

SELECT jobdetails.* 
FROM jobdetails
CROSS APPLY  (select value 
              from STRING_SPLIT('540%,%144,orange,coconut',',') 
              WHERE jobdetails.job_no 
              like value) as leek

It wouldn't take very much more work to turn that into a reusable function

ShrapNull
  • 1,090
  • 1
  • 9
  • 15
0

I had this same question and found a very simple solution using the SUBSTRING function in the WHERE clause. This will not affect how the job_no displays in the return, rather it just trims the IN search down based on the criteria entered for the substring function.

The advantage of using SUBSTRING versus LEFT or RIGHT is that you can define the starting character so if you just want to search the middle of a string, you can do so.

SELECT *
FROM jobdetails
WHERE SUBSTRING(job_no, 1, 4) IN ('0711', '0712')
Willie
  • 1
-1

You have the answer right there in your question. You cannot directly pass wildcard when using IN. However, you can use a sub-query.

Try this:

select *
from jobdetails
where job_no in (
select job_no
from jobdetails
where job_no like '0711%' or job_no like '0712%')
)

I know that this looks crazy, as you can just stick to using OR in your WHERE clause. why the subquery? How ever, the subquery approach will be useful when you have to match details from a different source.

Raj

Raj
  • 10,653
  • 2
  • 45
  • 52
  • 1
    Why would you need the subquery and instead just put the subquery or as the main query or? – Dusty Jul 02 '09 at 19:20
-1

Try this

select * 
from jobdetails 
where job_no between '0711' and '0713'

the only problem is that job '0713' is going to be returned as well so can use '07299999999999' or just add and job_no <> '0713'

Dan zamir

EdChum
  • 376,765
  • 198
  • 813
  • 562
  • Although this doesn't answer the question. It is helpful in my case where I can at least reduce the query result size and then continue filtering with my client side code. – Rick Love Mar 28 '19 at 15:43
-1

I'm just learning this stuff but would this work?

select *
from jobdetails
where job_no regexp "^(071)[1|2]";
-4

This might me the most simple solution use like any

select *
from jobdetails
where job_no like any ('0711%', '0712%')

In Teradata this works fine.

Samer
  • 1,923
  • 3
  • 34
  • 54
Pablo
  • 1