I have a table mapping postal code ranges to contacts. Postal codes are saved in multiple formats for different countries.
Table postcode-range:
FROM-CODE TO-CODE CONTACT-ID COUNTRY-CODE
12000 12999 18 fr
BT000000 BT9ZZZZZ 34 uk
...
To find a contact in a specific range , e.g. range starting with 123, I use the following query:
select * from postcode-range
where '123' between from-code and to-code
and country-code = 'fr'
This will return the first entry, contact-id 18.
The problem is if I search for '120' or '12' I get no results.
Any idea what's wrong here? Anybody got an alternative SQL query?
'12' < '120' < '12000'
If you change your from and to codes to '12' and '12999' for 'fr' your query as written will work, although it would include patterns such as '121AB' which presumably isn't a valid French post code. You could include other validation such as testing that the string contains only numbers, or its length.
e.g. do
like '12[0-9][0-9][0-9]'
I found this solution:
select * from postcode-range
where country-code = 'fr'
and left('12' + '00000000000000', len(from-code)) between from-code and to-code
If the query is shorter than the required length of the postal codes, then the missing characters are filled by zeros. I simply assume that no postal code is longer than 14 characters.
The country-code and query (here '12') are just place-holders.
You could use LIKE '12%'
or use lpad to get the 1st 3 characters.
Related
enter image description here
Hey I'm looking to do a query which allows me to see how many citties have starting phone number with number 6 and the other between 7-9
SELECT COUNT(Ciudad) AS "T.Fijos", Ciudad
FROM "BBDD.CLIENTES"WHERE Teléfono LIKE "9%"
GROUP BY Ciudad
that query only shows me phone number starting with 9 I need to do all in one query
Please try the following.
However, I wonder whether your FROM should in fact be FROM "BBDD"."CLIENTES". By wrapping the entire name in double-quotes in that way, you are saying that the table name is "BBBD.CLIENTES" and not specifying a schema.
Unfortunately I am unable to test this on SQLite, but it should be generally OK.
We can use a common table expression (CTE - the WITH... part) to create a temporary view of the data including a new column for the starting digit.
Then we can use CASE WHEN ... to check what the start digit is and return some text describing that digit.
WITH t
AS
(
SELECT Ciudad,
"Teléfono",
CAST(SUBSTR(Teléfono,1,1) AS integer) AS starting_digit
FROM "BBDD.CLIENTES"
)
SELECT Ciudad,
'Teléfono starts with ' ||
CASE
WHEN starting_digit = 6 THEN '6'
WHEN starting_digit BETWEEN 7 AND 9 THEN '7, 8 or 9'
ELSE 'something else'
END AS phone_start,
COUNT(*) AS count_of_phone_numbers
FROM t
GROUP BY 1, 2;
I am trying to do this query (updated after comments)
SELECT item,short,itemgr FROM DATABASE.ITEM
WHERE marker = 0 and
itemgr in ('200','201','202','204','205','230','234','236','240','270','285') and
short NOT LIKE '%AQUA%';
The results vary. If I use NOT LIKE after the first bracket with 1 parameter it works (as you can see it in the sample now), but as soon as I try to add a second NOT LIKE command I just get the results from the first bracket.
EDIT
Original SQL:
SELECT item,short,itemgr FROM DATABASE.ITEM
WHERE
marker = 0 AND (itemgr = '100' OR itemgr = '301' OR itemgr = '405')
AND
(short NOT LIKE '%A%' OR short NOT LIKE '%B%' OR short NOT LIKE '%A%');
If you want to get items that don't match a series of like conditions, I would suggest regular expressions. Perhaps what you want is:
SELECT item, short, itemgr
FROM DATABASE.ITEM i
WHERE i.marker = 0 and
i.itemgr in ('200', '201', '202', '204', '205', '230', '234', '236', '240', '270', '285') and
not regexp_like(short, 'AQUA|TERRA')
Negative logic is always difficult to understand. Try to write code in which you state what you want instead of what you don't want.
In this case, instead of looking for values in SHORT which don't contain letters, look for values which do contain the characters you care about:
SELECT item,short,itemgr
FROM DATABASE.ITEM
WHERE marker = 0 AND
(itemgr = '100' OR itemgr = '301' OR itemgr = '405') AND
REGEXP_LIKE(SHORT, '^[0-9 ]+$')
In this case this regular expression says that the query will only accept rows where the value of SHORT consists entirely of the characters '0', '1', ..., '9', and ' '.
db<>fiddle here
Regular expressions are a useful tool. If you're not familiar with them I suggest finding a resource (book, web site, etc) to help you learn about them.
It is not clear for me what you are trying to achieve but I have 2 advices:
Instead of itemgr = '100' OR itemgr = '301' OR itemgr = '405'" use "itemgr in ('100','301','405')"
"OR short NOT LIKE '%A%'" is redundant
I'm using RegEx in a View in Oracle 11g and I need to display certain codes that have an 'S' in the 8th position.
Using https://regexr.com/2v41h,
I was able to display these results with
REGEXP_SUBSTR(code, '\S{8}')
Y38.9X2S
Y38.9X2D
Y38.9X2A
Y38.9X1S
My issue is that I need to return only the values that have an 'S' in the last position which is the 8th position counting the decimal. What expression should I use?
Example:
Y38.9X2S
Y38.9X1S
I have tried:
REGEXP_SUBSTR(code, '\b[S]*[8]\b') AS CODE
Thank you in advance for your help.
I am thinking:
select substr(code, -8)
from t
where code like '%_______S'
If the code is always long enough, just use '%S'.
Or, as a case expression:
select (case when code like '%_______S' then substr(code, -8) end)
You will need regular expressions if code has other characters but they may not be necessary.
I've been asked to run a query to return a list of UK post codes from a table full of filters for email reports which only have 1 number at the end. The problem is that UK post codes are of variable length; some are structured 'AA#' or 'AA##' and some are structured 'A#' or 'A##'. I only want those that are either 'AA#' or 'A#'.
I tried running the below SQL, using length and (attempting to) use regex to filter out all results which didn't match what I wanted, but I'm very new to using ranges and it hasn't worked.
SELECT PostCode
FROM ReportFilterTable RFT
WHERE RFT.FilterType = 'Postcode'
AND LEN(RFT.Postcode) < 4
AND RFT.PostCode LIKE '%[0-9]'
I think the way I'm approaching this is flawed, but I'm clueless as to a better way. Could anyone help me out?
Thanks!
EDIT:
Since I helpfully didn't include any example data originally, I've now done so below.
This is a sample of the kind of values in the column I'm returning, with examples of what I need to return and what I don't.
B1 -- Should be returned
B10 -- Should not be returned
B2 -- Should be returned
B20 -- Should not be returned
B3 -- Should be returned
B30 -- Should not be returned
SE1 -- Should be returned
SE10 -- Should not be returned
You could filter for one or two letters (and omit the length check, since it's implicit in the LIKE):
WHERE RFT.FilterType = 'Postcode' AND
(RFT.PostCode LIKE '[A-Z][0-9]' OR RFT.PostCode LIKE '[A-Z][A-Z][0-9]')
If the issue is that you are getting values with multiple digits and you are using SQL Server (as suggested by the syntax), then you can do:
WHERE RFT.FilterType = 'Postcode' AND
LEN(RFT.Postcode) < 4 AND
(RFT.PostCode LIKE '%[0-9]' AND RFT.PostCode NOT LIKE '%[0-9][0-9]')
Or, if you know there are at least two characters, you could use:
WHERE RFT.FilterType = 'Postcode' AND
LEN(RFT.Postcode) < 4 AND
RFT.PostCode LIKE '%[^0-9][0-9]'
Non-digit followed by 1 digit ... LIKE '%[^0-9][0-9]'
I am not able to make this out: Between eliminates use of >= and <=
...but when i tried this query:
SELECT *
FROM names
WHERE name >= 'Ankit'
AND name <= 'P'
...it gives output:
name
------
Ankit
Mac
Bob
When I tried:
SELECT *
FROM names
WHERE name BETWEEN 'Ankit' AND 'P'
...it gives output:
name
------
Ankit
Can you explain this why?
First, Oracle VARCHAR2 type is case sensitive.
Second, check that you do not have spaces in the beginning of name like this:
" Bob"
" Mac"
Use trim function to check if this causes the problem:
SELECT *
FROM names
WHERE trim(name) BETWEEN 'Ankit' AND 'P'
If this does not help, check that language and sort order are correct for your database.
Edit:
Since above advice did not solve your problem, you could try following:
Maybe you have some other non-printable characters in field. Use Oracle DUMP function to check:
SELECT DUMP(name), name FROM names
You should get something like this:
Typ=1 Len=3: 66,111,98 Bob
...
Verify that Len is correct length.
Check NLS parameters so that they are not inadvertently changed to something that does not work for your database:
SELECT * FROM NLS_SESSION_PARAMETERS
SELECT * FROM NLS_DATABASE_PARAMETERS
SELECT * FROM NLS_INSTANCE_PARAMETERS
Check results of these three queries and verify that parameters on sort, language and character set are correct.
I'm quite certain this has nothing to do with your syntax and everything to do with your DB setup. I've recreated your test scenario and, like others, have no problem with either query returning the results you expect. Did you check your NLS_SESSION_PARAMETERS as mentioned earlier?
SQL code is case insensitive.
String values and string comparisons are case sensitive.
See for yourself:
SELECT CASE WHEN 'a' = 'A' THEN 'string comparison is case insensitive'
WHEN 'a' <> 'A' THEN 'string comparison is case sensitive'
END
FROM dual;
You seem to have used a lowercase 'p' in the top query and an uppercase 'P' in the second. Was this intentional?
SELECT *
FROM names
WHERE name BETWEEN 'Ankit' AND 'P'
also should return all three rows - I just verified that it does so using your example. Are you sure that you made the test correctly? Maybe you inserted data in other session and didn't commit additional rows?
Nut 100% sure about it, but as it's only 3 rows, you could try it:
SELECT *
FROM names
WHERE (name BETWEEN "Ankit" AND "P")
OR (name BETWEEN "ankit" AND "p")