BETWEEN is used in a WHERE clause to select a range of data between two values.
If I am correct whether the range's endpoint are excluded or not is DBMS specific.
What I can not understand in the following:
If I have a table of values and I do the following query:
SELECT food_name
FROM health_foods
WHERE calories BETWEEN 33 AND 135;`
The query returns as results rows including calories =33 and calories =135 (i.e. range endpoints are included).
But if I do:
SELECT food_name
FROM health_foods
WHERE food_name BETWEEN 'G' AND 'O';
I do not get rows with food_name starting with O. I.e. the end of the range is excluded.
For the query to work as expected I type:
SELECT food_name
FROM health_foods
WHERE food_name BETWEEN 'G' AND 'P';`
My question is why is there such a difference for BETWEEN for numbers and text data?
Between is operating exactly the same way for numbers and for character strings. The two endpoints are included. This is part of the ANSI standard, so it is how all SQL dialects work.
The expression:
where num between 33 and 135
will match when num is 135. It will not match when number is 135.00001.
Similarly, the expression:
where food_name BETWEEN 'G' AND 'O'
will match 'O', but not any other string beginning with 'O'.
Once simple kludge is to use "~". This has the largest 7-bit ASCII value, so for English-language applications, it usually works well:
where food_name between 'G' and 'O~'
You can also do various other things. Here are two ideas:
where left(food_name, 1) between 'G' and 'O'
where food_name >= 'G' and food_name < 'P'
The important point, though, is that between works the same way regardless of data type.
Take the example of 'Orange' vs. 'O'. The string 'Orange' is clearly not equal to the string 'O', and as it is longer, it must be greater, not less than.
You could do 'Orange' < 'OZZZZZZZZZZZZZZ' though.
try this with REGEX
WHERE food_name REGEXP '^[G-O]';
this gives you all food_name wich starts by G till those who starts by O
DEMO HERE
Related
I have a SQL Table in that i use BETWEEN Operater.
The BETWEEN Operater selects values within range. The values can be numbers, text , dates.
stu_id name city pin
1 Raj Ranchi 123456
2 sonu Delhi 652345
3 ANU KOLKATA 879845
4 K.K's Company Delhi 345546
5 J.K's Company Delhi 123456
I have a query like this:-
SELECT * FROM student WHERE stu_id BETWEEN 2 AND 4 //including 2 & 4
SELECT * FROM `student` WHERE name between 'A' and 'K' //including A & not K
Here My Question is why not including K.
but I want K also in searches.
Don't use between -- until you really understand it. That is just general advice. BETWEEN is inclusive, so your second query is equivalent to:
WHERE name >= 'A' AND
name <= 'K'
Because of the equality, 'K' is included in the result set. However, names longer than one character and starting with 'K' are not -- "Ka" for instance.
Instead, be explicit:
WHERE name >= 'A' AND
name < 'L'
Of course, BETWEEN can be useful. However, it is useful for discrete values, such as integers. It is a bit dangerous with numbers with decimals, strings, and date/time values. That is why I encourage you to express the logic as inequalities.
In supplement to gordon's answer, one way to get what you're expecting is to turn your name into a discrete set of values:
SELECT * FROM `student` WHERE LEFT(name, 1) between 'A' and 'K'
You need to appreciate that K.K's Company is alphabetically AFTER the letter K on its own so it is not BETWEEN, in the same way that 4.1 is not BETWEEN 2 and 4
By stripping it down to just a single character from the start of the string it will work like you expect, but take cautionary note, you should always avoid running functions on values in tables, because if you had a million names, thats a million strings that mysql has to strip out to just the first letter and it might no longer be able to use an index on name, battering the performance.
Instead, you could :
SELECT * FROM `student` WHERE name >= 'A' and name < 'L'
which is more likely to permit the use of an index as you aren't manipulating the stored values before comparing them
This works because it asks for everything up to but not including L.. Which includes all of your names starting with K, even kzzzzzzzz. Numerically it is equivalent to saying number >= 2 and number < 5 which gives you all the numbers starting with 2, 3 or 4 (like the 4.1 from before) but not the 5
Remember that BETWEEN is inclusive at both ends. Always revert to a pattern of a >= b and a < c, a >= c and a < d when you want to specify ranges that capture all possible values
Compare in lexicographical order, 'K.K's Company' > 'K'
We should convert the string to integer. You can try that mysql script with CAST and SUBSTRING. I've updated your script here. It will include the last record as well.
SELECT * FROM student WHERE name CAST(SUBSTRING(username FROM 1) AS UNSIGNED)
BETWEEN 'A' AND 'K';
The script will work. Hope it will helps to you.
Here I've attached my test sample.
Need help with this, as I am stumped with how to set the query update.
I will like to replace occurrences of 10x to 20x where x must be a numeric number. Also the numeric number can occur in any position. And the first two numeric digit of the numeric occurrence must be a 10
eg: tableA - at field colA has the followings:
TOK101s
102YUZ
TAIP103v
ECC10
ECC10a
SCC_103
TD-102b
ZA1104z
Result after the query update should be:
TOK201s
202YUZ
TAIP203v
ECC10
ECC10a
SCC_203
TD-202b
ZA1104z
ECC10 and ECC10a should not be updated since the 3rd char after 10 is not a numeric value.
ZA1104z should not be updated bec the numeric string 1104 does not begin with 10.
Thanks to Barmar and Misaka for:
SQL: search/replace but only the first time a value appears in record
update tableA set colA = IF(INSTR(colA, '10') <> 0, CONCAT(LEFT(colA, INSTR(colA, '10') - 1), '20', SUBSTRING(colA FROM INSTR(colA, '10') + CHAR_LENGTH('10'))), colA) where colA REGEXP '(^|[^0-9])10[0-9]'
The above helped me to get what I wanted.
I am having an issue with the following:
Inside my table I have the following:
ID Long Latt city
1 n/a n/a Newcastle-upon-Tyne
2 n/a n/a Newcastle Upon Tyne
3 n/a n/a Stoke-on-Trent
4 n/a n/a Stoke on Trent
If someone enters in the search "Newcastle Upon Type" I want both of them to show. My sql statement is:
select * from `properties` where `city` LIKE '%Newcastle Upon Tyne%'
But only one shows? But it's a LIKE statement, "Newcastle-Upon-Tyne" and "Newcastle Upon Tyne are similar - So why is only the exact match showing in this instance?
The LIKE comparison is returning TRUE only for that one row.
The LIKE comparison is essentially equivalent to an equality comparison
SELECT 'ab d' = 'ab d' --> TRUE
, 'ab d' LIKE 'ab d' --> TRUE
The difference is that LIKE supports two wildcard characters in the values on the right side.... the percent sign character (%) and the underscore character (_). The % character matches zero, one or more of any character. The _ character matches any one single character.
Compare the results from
city LIKE 'Newcastle_Upon_Tyne'
city LIKE 'Newcastle%Upon%Tyne'
Both of those would evaluate to true for values of city
'Newcastle-Upon-Tyne'
'Newcastle7Upon4Tyne'
Additionally, the one with the percent signs would also evaluate to TRUE for values of city such as
'NewcastleUpon56789Tyne'
'Newcastle FEE- UponFI Tyne'
If you want more precise matching than is provided by the LIKE comarison, you could use a regular expression instead..
city REGEXP 'Newcastle[ -]Upon[ -]Tyne'
This would return TRUE for city values
'Newcastle Upon Tyne'
'Newcastle-Upon Tyne'
'Newcastle Upon-Tyne'
'Newcastle-Upon-Tyne'
Because a space is not a wildcard character. A space is just like any other letter in a like statement. If you do something like this:
select * from `properties` where `city` LIKE '% %'
It will find all of the records that contain a space.
If you want any records that contain the words in that order, regardless of the characters between them, you can do this:
select * from `properties` where `city` LIKE '%Newcastle%Upon%Tyne%'
I have a field in the mysql database that contains data like the following:
Q16
Q32
L16
Q4
L32
L64
Q64
Q8
L1
L4
Q1
And so forth. What I'm trying to do is pull out, let's say, all the values that start with Q which is easy:
field_name LIKE 'Q%'
But then I want to filter let's say all the values that have a number higher than 32. As a result I'm supposed to get only 'Q64', however, I also get Q4, Q8 and so for as I'm comparing them as strings so only 3 and the respective digit are compared and the numbers are in general taken as single digits, not as integers.
As this makes perfect sense, I'm struggling to find a solution on how to perform this operation without pulling all the data out of the database, stripping out the Qs and parsing it all to integers.
I did play around with the CAST operator, however, it only works if the value is stored as string AND it contains only digits. The parsing fails if there's another character in there..
Extract the number from the string and cast it to a number with *1 or cast
select * from your_table
where substring(field_name, 1, 1) = 'Q'
and substring(field_name, 2) * 1 > 32
Hi I want to sort a table .The field contains numbers,alphabets and numbers with alphabets ie,
1
2
1a
11a
a
6a
b
I want to sort this to,
1
1a
2
6a
11a
a
b
My code is, SELECT * FROM t ORDER BY CAST(st AS SIGNED), st
But the result is,
a
b
1
1a
2
6a
11a
I found this code in this url "http://www.mpopp.net/2006/06/sorting-of-numeric-values-mixed-with-alphanumeric-values/"
Anyone please help me
This would do your required sort order, even in the presence of 0 in the table;
SELECT * FROM t
ORDER BY
st REGEXP '^[[:alpha:]].*',
st+0,
st
An SQLfiddle to test with.
As a first sort criteria, it sorts anything that starts with a letter after anything that doesn't. That's what the regexp does.
As a second sort criteria it sorts by the numerical value the string starts with (st+0 adds 0 to the numerical part the string starts with and returns an int)
As a last resort, it sorts by the string itself to get the alphabetical ones in order.
You can use this:
SELECT *
FROM t
ORDER BY
st+0=0, st+0, st
Using st+0 the varchar column will be casted to int. Ordering by st+0=0 will put alphanumeric rows at the bottom (st+0=0 will be 1 if the string starts with an alphanumeric character, oterwise it will be 0)
Please see fiddle here.
The reason that you are getting this output is that all the character like 'a', 'b' etc are converted to '0' and if you use order by ASC it will appear at the top.
SELECT CAST(number AS SIGNED) from tbl
is returning
1
2
1
11
0
6
0
Look at this fiddle:- SQL FIDDLE
I did small change in your query -
SELECT *, CAST(st AS SIGNED) as casted_column
FROM t
ORDER BY casted_column ASC, st ASC
this should work.
in theory your syntax should work but not sure why mysql doesn't accept these methods after from tag.
so created temp field and then sorted that one .
This should work as per my experience, and you can check it.
SQL FIDDLE