Why do the single quotes in this SQL query affect the calculations? - mysql

SELECT COUNT(*) FROM planets
WHERE ROUND(SQRT(POWER(('71' - coords_x), 2) +
POWER(('97' - coords_y), 2))) <= 17
==> 51
SELECT COUNT(*) FROM planets
WHERE ROUND(SQRT(POWER((71 - coords_x), 2) +
POWER((97 - coords_y), 2))) <= 17
==> 22
coords_x and coords_y are both TINYINT fields containing values in the range [1, 100]. Usually MySQL doesn't care if numbers are quoted or not.. but apparently it does in this case. The question is: Why?

I am a bit rusty on the inerds of MySql but <= on string goes to lexicographical sorting instead of numeric ie, '150' < '17'.

The implicit conversion from string to floating point number is probably causing in inaccurate results. See: Type Conversion in Expression Evaluation

Related

MariaDB SQL query returns truncated numbers from select statement

I am trying to pull data from Maria DB. The datatype in schema is DECIMAL (12, 8).
In my program when I query using following query. it trucates to 4 (or 3) decimal places and also round off.
select CAST(FORMAT(latitude, 100) AS FLOAT) latitude from mytable
it returns 36.173 . In DB it is stored as 36.17298200
I want it to return as 36.172982
To use the number in calculations, simply use it. No conversion, no CAST.
To dislay it to 6 decimal places, do that on SELECTing:
SELECT FORMAT(latitude, 6) ...
FORMAT(..., 100) should give you lots of decimal places.
FLOAT does not have enough precision to distinguish more than 6 or 7 significant decimal places. That is, the first and third numbers nere are the closest representable numbers in FLOAT:
x4210b122 --> 36.172981262207
36.17298200
x4210b123 --> 36.172985076904
Double:
x40421624463065f9 --> 36.1729819999999975
For Latitude and Longitude:
FLOAT has a resolution of 1.7 m or 5.6 ft -- good enough for Vehicles
DECIMAL(8,6) 16 cm 1/2 ft -- Friends in a mall
According to official MySQL documents:
The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it is important to preserve exact precision, for example with monetary data. In MySQL, NUMERIC is implemented as DECIMAL, so the following remarks about DECIMAL apply equally to NUMERIC.
Floating-Point Types (Approximate Value) - FLOAT, DOUBLE
So you should be writing something similar to:
select CAST(FORMAT(latitude, 100) AS DECIMAL(8,6)) latitude from mytable
As 8 is the total number of digits and 6 is precision.

Mysql date function not working for less than

I need to get all records those equal and less than 2012-12-28 i used bellow query for this,
booking_time is DATETIME field, and there are records less than 2012-12-28 but it returns zero rows.
does anyone has idea ?
SELECT * FROM ctx_bookings WHERE DATE(booking_time)<=2012-12-28 ORDER BY id ASC
Table filed
+---------------------+
| booking_time |
+---------------------+
| 2012-12-20 03:10:09 |
| 2012-12-25 02:10:04 |
+---------------------+
Please anybody know why is this happening ?
wrap the value with single quote and surely it will work
SELECT *
FROM ctx_bookings
WHERE DATE(booking_time) <= '2012-12-28'
ORDER BY id ASC
SQLFiddle Demo
As documented under Date and Time Literals:
MySQL recognizes DATE values in these formats:
As a string in either 'YYYY-MM-DD' or 'YY-MM-DD' format. A “relaxed” syntax is permitted: Any punctuation character may be used as the delimiter between date parts. For example, '2012-12-31', '2012/12/31', '2012^12^31', and '2012#12#31' are equivalent.
As a string with no delimiters in either 'YYYYMMDD' or 'YYMMDD' format, provided that the string makes sense as a date. For example, '20070523' and '070523' are interpreted as '2007-05-23', but '071332' is illegal (it has nonsensical month and day parts) and becomes '0000-00-00'.
As a number in either YYYYMMDD or YYMMDD format, provided that the number makes sense as a date. For example, 19830905 and 830905 are interpreted as '1983-09-05'.
As #Barmar commented, your literal expression 2012-12-28 is evaluated as the arithmetic (2012 - 12) - 28, which equals 1,972.
Per #JW.'s answer, you can quote that expression to obtain a valid date literal (of the first form, above). Alternatively:
whilst still quoting the literal, you could use any other punctuation character (or even no character) as the delimiter between date parts:
WHERE DATE(booking_time) <= '2012_12_28'
WHERE DATE(booking_time) <= '20121228'
you could remove the delimiters and leave your literal unquoted:
WHERE DATE(booking_time) <= 20121228
Note also that using a filter criterion like this, which uses a function (in this case, the DATE() function) over a column, requires a full table scan in order to evaluate that function—it therefore will not benefit from any indexes. A more sargable alternative would be to filter more explicitly over the range of column values (i.e. times) that satisfy your criteria:
WHERE booking_time < '2012-12-28' + INTERVAL 1 DAY
This is equivalent because any time that falls strictly prior to the following day will necessarily have occurred on or before the day of interest. It is sargable because the column is compared to a constant expression (the result of the + operation being deterministic), and therefore an index over booking_time can be traversed to immediately find all matching records.
SELECT * FROM ctx_bookings WHERE DATE(booking_time)<='2012-12-28' ORDER BY id ASC
try this mate

MySQL pattern matching with character exception

I'm trying to compare the results of two queries, one acquiring call IDs for calls made to my Asterisk server externally (10 digits) and the other acquiring call IDs connected to FROM the server (11 digits). The outbound calls are prepended a '1' before their number. Currently I'm using a statement like the following:
select data2, from_unixtime(time_id) day from queuemetrics.queue_log
where time_id > '1346475600' and (data2, time_id) in
(select dst, unix_timestamp(calldate) from asteriskcdrdb.cdr
where calldate > '2012-09-01' and lastdata like <blocked for privacy>)
order by day;
data2 is the column holding the 10 digit numbers, dst holds the 11 digit numbers. Is there a way I can pattern match the 2-11th characters of a column ONLY? To just skip over the first one? Obviously a LIKE or RLIKE would be useful, but I really need to maintain the nested query for this to work. Any help would be great. Also, pay no attention to my weird use of from_unixtime and unix_timestamp. I was experimenting with figuring if I needed my times in the same format for the search to work. Not important.
You may use RIGHT to extract the rightmost characters of a string:
RIGHT(your_field_here, 10);
If there are some characters you want to ignore at the beginning AND at the end of the string, then you may use SUBSTR:
SUBSTR(your_field_here, 2, 10);
Your query would then be:
SELECT data2, FROM_UNIXTIME(time_id) day FROM queuemetrics.queue_log
WHERE time_id > '1346475600' AND (data2, time_id) IN
(SELECT SUBSTR(dst, 2, 10), UNIX_TIMESTAMP(calldate) FROM asteriskcdrdb.cdr
WHERE calldate > '2012-09-01' AND lastdata LIKE <blocked for privacy>)
ORDER BY day;
Why not trim the leading digit from your dst field?

What does the use of an asterisk (*) mean in a mysql select statement, other than a wildcard?

I came across a mysql query that looks like this:
SELECT
SUM(some_amount*(some_field!=90)*(some_date < '2011-04-22'))
, SUM(some_amount*(some_field =90)*(some_date < '2011-04-22')*(another_field IS NULL))
FROM
some_table
What does the * mean in the select statement in this case?
Looks like CAST() is not necessary for boolean-to-integer conversions. Multiplication is used to convert the sum to 0 for unwanted rows (using the fact that boolean true can be cast to 1 and false to 0):
some_amount*(some_field!=90)*(some_date < '2011-04-22')
if some_field == 90 or some_date >= '2011-04-22', the corresponding term will evaluate to 0, thereby converting the entire expression to 0.
It is a multiplication operation.
example 2*3=6
It's a standard multiplication operator,
select 2 * 2
= 4
:)

What is the behavior for the minus operator between two datetimes in MySQL?

The difference between to datetimes is the number of seconds between them. This seems to work only if the datetimes occur in the same hour.
Why is this?
mysql> update events set created_at = "2011-04-13 15:59:59", fulfilled_at ="2011-04-13 16:00:00" where id = 1;
mysql> select fulfilled_at - created_at, timediff(fulfilled_at, created_at) from events where id = 1;
+---------------------------+------------------------------------+
| fulfilled_at - created_at | timediff(fulfilled_at, created_at) |
+---------------------------+------------------------------------+
| 4041.000000 | 00:00:01 |
+---------------------------+------------------------------------+
I know I should be using timediff, but I'm just curious why I'm seeing this or if it's documented somewhere.
MySQL is just converting strings into numbers as best it can, so that it can do the mathematical operation on them. In this case, its just stripping out all of the non numerical colons, dashes and spaces.
Try this:
SELECT (20110413155959 - 20110413160000) AS dates;
Your dates, without all the stuff that stops them being numbers - the result is -4041
Recall that mysql has two differente kinds of datetime-related substractions: The _SUB suffix is for substracting a date minus an interval, returning a date. The _DIFF suffix is for getting the difference between two dates, returning an interval (BTW, notice that only the first one has an inverse analog: _ADD)
The +/- signs are to be used for the first one (ADD/SUB), hence MYSQL expects an interval as a second argument.
DATE = DATE_ADD(DATE,INTERVAL) Also accepts +
DATE = DATE_SUB(DATE,INTERVAL) Also accepts -
INTERVAL = DATE_DIFF(DATE,DATE )
See doc here, the bit starting from:
Date arithmetic also can be performed using INTERVAL
together with the + or - operator...
Hence, it's incorrect to use the - to take the difference between two dates. Now, MYSQL, when confronted with incorrect outputs, tries to do its best guess (instead of throwing an error), sometimes that goes well, sometimes not.