Reputation: 19
I'm using Oracle SQL Developer and after executing this command only names starting with K
and L
show up. Why names starting with M
do not appear?
SELECT DISTINCT(names) FROM STUDENTS WHERE names BETWEEN 'K%' AND 'M%' ORDER BY 1 DESC;
And when I execute:
SELECT DISTINCT(names) FROM STUDENTS WHERE names BETWEEN 'K%' AND 'N%' ORDER BY 1 DESC;
K
,L
,M
appear but names starting with N
don't. BETWEEN
is inclusive so what's the problem?
This works perfectly:
SELECT * FROM STUDENTS WHERE year BETWEEN 1 AND 3;
Upvotes: 0
Views: 317
Reputation: 220877
The between predicate does not imply like
so you're simply comparing strings. Write this instead
-- Names with starting letters K, L, M, N
names >= 'K' AND names < 'O'
Alternatively, use regular expressions
-- Names with starting letters K, L, M
REGEXP_LIKE (names, '^[K-M]')
Upvotes: 5
Reputation: 1269823
Lukas explained the problem -- confusing LIKE
patterns with strings. One other solution is:
WHERE SUBSTR(names, 1, 1) BETWEEN 'K' AND 'M'
Note that of the solutions mentioned, only the direct comparison:
WHERE names >= 'K' AND names < 'O'
will use an index. However, with such a broad range of values, an index may not be useful for the query anyway.
Upvotes: 1
Reputation: 175716
BETWEEN is inclusive so what's the problem?
The wildcard '%' does not work as with LIKE
here and lexicographic order applies
SELECT CASE WHEN 'Mango' BETWEEN 'K%' AND 'M%' THEN 'true' ELSE 'false' END AS result
FROM dual
-- false
SELECT CASE WHEN 'Mango' >= 'K%' AND 'Mango' <= 'M%' THEN 'true' ELSE 'false' END
AS result
FROM dual
--false
SELECT CASE WHEN 'Mango' >= 'K%' THEN 'true' ELSE 'false' END AS result
FROM dual
-- true
SELECT CASE WHEN 'Mango' <= 'M%' THEN 'true' ELSE 'false' END AS result
FROM dual
-- false
This works perfectly:
SELECT * FROM STUDENTS WHERE year BETWEEN 1 AND 3;
Rewriting in similar manner(though it is not SARGable):
SELECT DISTINCT(names)
FROM STUDENTS
WHERE SUBSTR(names,1,1) BETWEEN 'K' AND 'M'
ORDER BY 1 DESC;
Upvotes: 1