LIKE [0-9] much slower than LIKE % - sql

I have a somewhat complex view that selects a bunch of items and the amount of stock they have remaining. I want to narrow down the result set to items codes that conform to a pattern so that unwanted items are filtered out.
The item codes that I want to include are formatted as a 4 digit number, followed by a hyphen followed by another 4 digit number
1234-0001
I also want to include item numbers that are formatted as an 13-digit number (an ISBN which starts with 978), followed by a hyphen, followed by another 2 digit number.
9781234567890-01
Originally I planned to use the below, which would match all item codes that included a hyphen in.
SELECT *
FROM Vw_Stock
WHERE ItemCode LIKE '%-%'
Unfortunately not all of our item codes are that uniform and people have sporadically used hyphens in items that do not conform to the two accepted formats above, so I switched to the following.
SELECT *
FROM Vw_Stock
WHERE ItemCode LIKE '[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]'
OR ItemCode LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]'
The query originally took 1 second and now it takes roughly 3 minutes 50 seconds. Why does it take so much longer? And is there a more efficient way for me to query against the item formats identified?

Related

Select entries with substring in a specific position of the word

I am trying to write an SQL query where my goal is to select all the entries that contains a substring in a specific position of a word (the entries are phrases with multiple words).
To make it clearer, suppose that I have these two entries (values inside a column, call it phrase):
1 - "Jamming in New York"
2 - "bosbessenjam 30g"
3 - "30g bosbessenjam"
4 - "Tranches de jambon fumé"
I want to select all the rows that contains a word that ends with "jam". So I want the second and third row.
I tried using LIKE '%jam%', however it just check the overall string and not the single word. So LIKE '%jam' returns the third row, but not the second.
Any idea on how to do this?

how to count occurrences of multiple words in a sql query

I have two tables one has a column containing words and their weightage. for example
word
weight
First
9
Second
4
third
6
fourth
7
and another table that has sentences. like
Sentence
Random column
this is first
..
Second sentence
..
another first
..
first and third word
..
now what i want to do is select words with weight 5 or more, and see how many sentence contain the keyword at-least once so the query result will be
(in the above example, I tried to handle scenarios like only one keyword is in the sentence, multiple in a single sentence, keyword not in any sentence.) Also if a keyword occurs multiple time in a sentence, the sentence should be counted once. I am trying to count sentences that contain the keyword, and not the number of keyword occurrence.
word
count
First
3
third
1
fourth
0
How to calculate this while keeping the query as simple as possible.(if possible)
If you want to count the number of sentences that contain the words, you can use:
select w.*,
(select count(*)
from sentences s
where s.sentence like concat('%', w.word, '%')
) as cnt
from words w
where weightage > 5;
This makes some assumptions on what you really mean.
"how many times each word is used in the sentence table" means "how many sentences contain the word at least once".
"used" can be handled by looking for the word anywhere in the sentence, regardless of surrounding characters.

Extract Number from VARCHAR

I have a [Comment] column of type VARCHAR(255) in a table that I'm trying to extract numbers from. The numbers will always be 12 digits, but aren't usually in the same place. Some of them will also have more than one 12 digit number, which is fine, but I only need the first.
I've tried using PATINDEX('%[0-9]%',[Comment]), but I can't figure out how to set a requirement of 12 digits.
An example of the data I'm working with is below:
Combined 4 items for $73.05 with same claim no. 123456789012 as is exceeding financial limits
Consolidated remaining amount of claim numbers, 123456789013, 123456789014, 123456789015, 123456789016 due to financial limits
You can just use 12 [0-9]'s in a row:
PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9‌​][0-9][0-9]%',[Comme‌​nt])

How to get Next 4 digit number from Table (Contains 3,4, 5 & 6, digit long numbers)

I found a good method of getting the next 4 digit number.
How to find next free unique 4-digit number
But in my case I want to get next available 4 or 5 digit number.
And this will change depending upon the users request. Theses number are not a key ID columns, but they are essential to the tagging structure for the business purpose.
Currently I use a table adabpter query. But how would I write a query.
I suppose I could do a long iterative loop through all values until I see a 4 digit.
But I'm trying to think of something more efficient.
Function GetNextAvailableNumber(NumofDigits) as Long
'SQL Code Here ----
'Query Number Table
Return Long
End Function
Here's my current SQL:
'This Queries my View
SELECT MIN([Number]) AS Expr1
FROM LineNumbersNotUsed
'This is my View SQL
SELECT Numbers.Number
FROM Numbers
WHERE (((Exists (Select * From LineList Where LineList.LineNum = Numbers.Number))=False))
ORDER BY Numbers.Number;
Numbers is the List of All available number from 0 to 99999, basically what's available to use.
LineList is my final master table where I keep the long and all the relevant other business information.
Hopefully this make sense.
Gosh you guys are so tough on new guys.
I accidentally hit the enter key, and the question posted and I instantly get -3 votes.
Give a new guy a break will you! Please.
I apologize in advance in case I overlooked something in your question. Using your design, won't a query like this return the next unused 4 digit number?
SELECT MIN([Number]) AS next_number
FROM LineNumbersNotUsed
WHERE
[Number] > 999
AND [Number] < 10000;
This approach is not adequate with multiple concurrent users, but you didn't indicate that is an issue for you.
The question you linked to explains that what you need is a table with 2 fields:
Number InUse
0000 No
0001 No
0002 Yes
0003 No
0005 Yes
Whenever a number is used/released, the table must be updated to set InUse to Yes/No.
Maybe I'm missing something, but from your explanation, and the SQL code you show us, it seems that you only have a table with a single field containing all numbers from 0 to 100000.
If that's the case, I don't see the usefulness of that table at all.
If I were you, and if I understand your need correctly, what you want is something like this:
First of all, create the table as above, with all running numbers from 0 to 100000, and a field for confirming if that number is used or not.
Initialise the InUse field with all the numbers already taken in your LineList table, something like:
UPDATE Numbers SET InUse = True
WHERE Numbers.Number IN (SELECT LineNum FROM LineList)
Write a function ReserveNumber(NumOfDigits as Integer) As Long to find and reserve a 4-digit or 5-digit free number following this logical sequence:
Depending on NumOfDigits (4 or 5) get the result of one of the queries as LowestNumber:
SELECT Min(Number) FROM Numbers WHERE Number < 10000 AND NOT InUse
SELECT Min(Number) FROM Numbers WHERE Number >= 10000 AND NOT InUse
Reserve that particular number to ensure it's not going to be used again:
UPDATE Numbers SET InUse = True WHERE Number = #LowestNumber
Return LowestNumber
Whenever
Notes: the logic above is a bit naive as it suppose that no two users will attempt to get the lowest number at the same time. There is however a risk that this may happen one day.
To remove that risk, you can, for instance, add a TakenBy column to the Numbers table and set it to the current username. Then, after you have reserved the number, read-it again to ensure that the TakenBy is really updated by the current client. If not, just try gain.
There are lots of ways to do this. You can try to fiddle around table locks as well, but whatever your solution, make sure you test it.

Generate unique random integer in database column

My application creates coupons that each need a unique barcode number. This number needs to be a positive integer and must be between 6 - 12 digits. This number represents a unique coupon, so this number must be unique. I can't simply increment the barcode numbers by 1, because this will make it easy for hackers to guess other coupon barcodes.
If I have a coupon db table, how can I generate this random barcode number and guarantee uniqueness?
This will give you a random number of up to 12 digits, with very few collisions.
select -convert(bigint, convert(varbinary(max), newid())) % 1000000000000
You need to test and ignore collisions, as well as discard numbers that end up with less than 6 digits.
EDIT
To use the lowest lengths first, you won't be able to use a truly random number generator. This is because once you get to 95% of the 6-digit range, the collisions would be so high that the program spends all its time trying and retrying to get a unique number that hasn't been used yet. Once you get to only one number remaining, the program can wait forever and never "generate" that number. So, to fulfil "lowest lengths first" you would actually have to generate ALL numbers into a table and then row number (order by len(num), newid()) them randomly, then sequentially draw them out.
To 0-pad to 12 digits, use
select right('000000000000'
+right(-convert(bigint, convert(varbinary(max), newid())),12),12)
Might sound lame, but depending on the # of values you're going to need, you could just put a unique constraint on the column, and update each row with a random number (with the 6-12 digits) and loop until it doesn't fail. 12 digits is a lot of values, so you're probably not going to get many collisions.