Does an AND statement in SQL always get executed? [duplicate] - mysql

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is the SQL WHERE clause short-circuit evaluated?
If we do
SELECT * FROM Business WHERE Latitude < 9 AND Latitude > 10
for example, will Latitude > 10 ever be called if Latitude is 8 for example?
What about in mysql?
What about in core data?
Is it dependent on SQL implementation or is there a definite standard that in where clause if one of the AND statement is false than the rest won't be executed.
I asked this to know whether I can save some computational power. Say the expression after the first AND is expensive to compute such as computing distance.

WARNING: down-to-earth answer
You have probably mistaken AND with OR (in fact condition Latitude < 9 AND Latitude > 10 makes no sense..).
OR conjunction AFAIK in most languages this is implemented as follows: every condition is checked until one is true (i believe this is also true with SQL - EDIT: this answer suggests that the actual behaviour is implementation-dependant, i.e. you can't take that for sure in any RDBMS)
AND conjunction every condition is checked until one is false
So you probably wanted to write this condition:
Latitude < 9 OR Latitude > 10
which is equivalent to:
NOT(Latitude >= 9 AND Latitude <= 10)

Related

rails difference between two dates inside .where

Here is my logic
I want to get the closest 4 more expensive mobiles to a specific mobile #mobile but under one condition the difference between the release dates of the two mobiles is not more than a year and half
Here is the query
high = Mobile.where("price >= #{#mobile.price} AND id != #{#mobile.id} AND visible = true").where("ABS(release_date - #{#mobile.release_date}) > ?", 18.months).order(price: :ASC).first(4)
The first .where() works perfectly but the second is not working and I get this error
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00 UTC) > 46656000) ORDER BY `mobiles`.`price` ASC LIMIT 4' at line 1: SELECT `mobiles`.* FROM `mobiles` WHERE (price >= 123123.0 AND id != 11 AND visible = true) AND (ABS(release_date - 2016-04-10 00:00:00 UTC) > 46656000) ORDER BY `mobiles`.`price` ASC LIMIT 4
I think now you can get my logic. What is the right syntax to achieve it?
A couple of tips here:
It is a dangerous practice to concatenate variables into your queries using the "#{}" operator. Doing so bypasses query parameterization and could leave your app open to SQL injection. Instead, use "?" in your where clause.
The reason MySQL is giving you an error is because you are concatenating a string into your query without encapsulating it in quotes.
With these two things in mind, I would start by refactoring your query like so:
high = Mobile.where("price >= ?", #mobile.price)
.where.not(id: #mobile.id)
.where(visible: true)
.where("ABS(release_date - ?) > 46656000", #mobile.release_date)
.order(price: :ASC).first(4)
You will note that I replaced 18.months with 46656000. This saves a few clock cycles in the Rails app. Depending on your database schema, the last where clause may not work. The modification below may end up working better.
As a further refinement, you could refactor your last where clause to look for a release date that is between 18 months before #mobile.release_date and 18 months after. The saves your MySql database from having to do the math on each record and may lead to better performance:
.where(release_date: (#mobile.release_date - 18.months)..(#mobile.release_date + 18.months) )
I do not know your database schema, so you may run into date conversion problems with the code above. I recommend you play with it in the Rails console.
Use a Range to query between dates/times:
Mobile.where("price >= ?", #mobile.price)
.where.not(id: #mobile.id)
.where(release_date: 18.months.ago..Time.now)
.order(price: :ASC)
.first(4)

Best way to check for near objects in SQL database according to x and y columns

I have a database with pretty static objects e.g buildings with x and y coorinates for a game in which I will be sending http requests to my server to get all objects around some given x and y coordinates.
Currently I am using this simple sql on the server which then returns the data in JSON.
SELECT OBJECTS.id \"id\", POINTS.x, POINTS.y
FROM OBJECT, OBJECTPOINTS, POINTS
WHERE OBJECTPOINTS.OID = OBJECTS.ID AND OBJECTPOINTS.PID = POINTS.ID AND
ABS(POINTS.x -\"+x+") < 0.01 AND ABS(POINTS.y - "+y+") < 0.01;"
Each object is represented by points which will be used to draw on the client.
I am currently achieving ~ 5 seconds respond time for around 1.5M Points and 200k objects.
To me this is fairly reasonable however the problem I have is that the db is blocked with each request. Here are 10 requests sent at the same time
:
36 seconds for map data with 10 clients requesting at the same time is way too much.
So my question is what would be a better way to handle the request rather then comparing distance in sql?
Would it be deliberatly faster to hold all of those objects in memory and iterate them on the server?
I have also thought of abstracting all the data in to some kind of grid and then first checking in which grid the request coords are to then run the same query as above on the db with only the objects in that certain square. Is there some clever solution I might be overlooking in the sql maybe?
Your query cannot be utilized by an index, because you are using a function on your column data in the where-clause of your query (ABS(POINTS.x ...)). If you rewrite your query to compare the raw value of your columns against another value you can add an index to your table and your query no longer needs to scan your full table to answer the query.
Rewrite your where clause to something like this to replace the ABS() function.
(POINTS.x < (x + 0.01) AND POINTS.x > (x - 0.01))
Then add an index to your table like:
alter table POINTS add index position(x, y);
Check the changing of the scanned rows of both queries with and without the index by adding the explain keyword infront of your query.

"30/360 = 0" Is This A Bug Or What? [duplicate]

This question already has answers here:
SQL Server, division returns zero
(6 answers)
Why does SQL Server round off results of dividing two integers?
(6 answers)
Database calculations are wrong
(1 answer)
Closed 9 years ago.
Ok I have A SQL Procedure I calculate some Payroll Stuff. The Problem here one of my equation '30/360 = 0' return 'zero' and try it on Sql Server Like this :
Select 30/360 --This Return Zero And Should Return '0.08333333'
This is not my real function, just example, Is this normal behavior?
Dividing two integers returns an integer. Use the following instead:
select 30/360.0

What database for 3D distance calculations?

All-
I thing i've finally out grown MySQL for one of my solutions. Right now I have 70 million rows that simply store the x,y,z of objects in 3D space. Unfortunately I don't know how else to optimize my database to handle the inserts/queries anymore. I need to query based on distance (get objects within distance).
Does anyone have a suggestions on a good replacement? I don't know if I should be looking at something like hbase or non-relational databases, as I may run into a similar problem. I generally insert about 100 rows per minute, and my query looks like:
// get objects within 500 yards
SELECT DISTINCT `object_positions`.`entry` FROM `object_positions` WHERE `object_positions`.`type` = 3 AND `object_positions`.`continent` = '$p->continent' AND SQRT(POW((`object_positions`.`x` - $p->x), 2) + POW((`object_positions`.`y` - $p->y), 2) + POW((`object_positions`.`z` - $p->z), 2)) < 500;
Nothing crazy complicated, but I think the math involved is what is causing MySQL to explode and I'm wondering if I should be looking at a cloud based database solution? It could easily have to handle 10-100 queries per second.
It's not MySQL that's giving you trouble, it's the need to apply indexing to your problem. You have a problem that no amount of NoSQL or cloud computing is going to solve by magic.
Here's your query simplified just a bit for clarity.
SELECT DISTINCT entry
FROM object_positions
WHERE type = 3
AND continent = '$p->continent'
AND DIST(x,$p->x, y, $p->y, z,$p-z) < 500
DIST() is shorthand for your Cartesian distance function.
You need to put separate indexes on x, y, and z in your table, then you need to do this:
SELECT DISTINCT entry
FROM object_positions
WHERE type = 3
AND continent = '$p->continent'
AND x BETWEEN ($p->x - 500) AND ($p->x + 500)
AND y BETWEEN ($p->y - 500) AND ($p->y + 500)
AND z BETWEEN ($p->z - 500) AND ($p->z + 500)
AND DIST(x,$p->x, y, $p->y, z,$p-z) < 500
The three BETWEEN clauses of the WHERE statement will allow indexes to be used to avoid a full table scan of your table for each query. They'll select all your points in a 1000x1000x1000 cube surrounding your candidate point. Then the DIST computation will toss out the ones that are outside the radius you want. You'll get the same batch of points but much more efficiently.
You don't have to actually create a DIST function; the formula you have in your question is fine.
You do have an index on (type, continent), don't you? If not you need it too.

SQL Server IN statement with wildcard [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a combination of “LIKE” and “IN” in SQL?
The first where clause below runs fine for me but it does not pick up contacts that might have 45211-1234 or 45213-4321
SELECT * FROM contacts
WHERE zipcode IN ('45211','45213')
I thought I could change the where clause to the below to fix, but it fails.
SELECT * FROM contacts
WHERE zipcode IN ('45211%','45213%')
How might I change this so it brings back anything that has proper zip + dash + any zip4? For example, 45211-1234 or 45213-4321.
Note I have whole bunch of zipcodes to enter, not just these two.
How about this:
SELECT * FROM contacts
WHERE Left(zipcode,5) IN ('45211','45213')