We number our animals with a 1-2 digit string prefix followed by a number. the total string length is 6.
When people enter new IDs, I'd like them to supply a string prefix, and write a SQL string to calculate the next ID in the series. The difficultly is that IDs can either be 1 character + 5 digits or 2 / 4. the patterns are:
rhXXXX
rXXXXX
cyXXXX
In a similar situation elsewhere I did this:
SELECT cast(SUBSTRING(MAX(Id), "+prefix.length+", 6) AS INTEGER) as number FROM study.Demographics d WHERE Id LIKE '" + prefix + "%'"
However, this breaks down b/c if the prefix is 'r', it will return IDs starting with both 'r' or 'rh'. the substring function throws an error. are there other ways to approach this? some questions i had were:
1. without using a regular expression, can I make a smarter pattern matching in the WHERE clause than i'm doing?
2. is there a way to write "d.Id like 'r% AND 'the rest of the ID is numeric'" in labkey SQL?
3. assuming I cannot write a smarter WHERE clause, can I approach the SUBSTRING better?
Note: I'm passing this to JS code, so I could do some processing there. I'd like to offload whatever I can to SQL if possible though. I was considering something like:
SELECT SUBSTRING(MAX(Id), "+prefix.length+", 6) as max, SUBSTRING(min(Id), "+prefix.length+", 6) as min,FROM study.Demographics d WHERE Id LIKE '" + prefix + "%'"
then let the client take these 2 values and figure out which to use. this or something similar might work, but it seems fragile. |
|
Ben Bimber responded: |
2011-06-20 14:28 |
i dont know what i was thinking with that second SQL idea. please ignore that. any insight into sorting out the character vs digit portion of a string would still be appreciated. thanks. |
|
Ben Bimber responded: |
2011-06-20 15:10 |
i didnt realize the postgres pass-through function included some regular expression functions. this seems to works ok. the purpose of the ucase() = lcase() in the WHERE clause is a proxy for whether the substring has characters or not. i'd still be curious to know if there's a better way to do that.
var sql = "
SELECT max(regexp_replace(SUBSTRING(Id, "+(prefix.length+1)+", 6), '[a-z]+', '')) as maxNumber
FROM study.Demographics
WHERE Id LIKE '" + prefix + "%' AND lcase(SUBSTRING(Id, "+(prefix.length+1)+", 6)) = ucase(SUBSTRING(Id, "+(prefix.length+1)+", 6))"; |
|
trent responded: |
2011-06-21 16:48 |
Another technique I've seen to remove alpha characters;
translate(val,translate(val, '1234567890',''),'')
where val is the column containing the data.
So,
select max(translate(val,translate(val, '1234567890',''),'')) as MAX_ID
from table
Ta,
Trent |
|
jeckels responded: |
2011-06-22 18:23 |
Hi Ben,
Be sure that if you're doing a MAX, you're doing it on a number and not a string. '9' > '100000'
Thanks,
Josh |
|
|
|