Mike Mike - 1 month ago 6
MySQL Question

Insert an X and Y into a MySQL database that does not already exist

I have a basic database table for a grid

CREATE TABLE `grid` (
`id` int(10) unsigned NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`customers_id` int(10) unsigned NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
`seen` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


I'm trying to get an x and y value from the grid that doesn't already exist in the grid. (with means to use it as part of an insert later) I'm using the following but, sometimes, it returns a set of coordinates that do already exist...

PHP

private $_maxColumns = 144;
private $_maxRows = 90;


MySQL (Within quotes in PHP - hence the curly brackets around the variables)

SELECT
CONCAT(
FLOOR( (RAND() * ( {$this->_maxColumns} - 1 + 1 ) ) + 1 ),
'-',
FLOOR( (RAND() * ( {$this->_maxRows} - 1 + 1 ) ) + 1 )
) as 'random'

FROM `grid`

WHERE 'random' NOT IN (
SELECT CONCAT( `x`, '-', `y` ) FROM `grid`
)


Any help is much appreciated!

Answer

It returns existing values because you got the filter completely wrong:

WHERE 'random' NOT IN (
    SELECT CONCAT( `x`, '-', `y` ) FROM `grid`

In the where criteria you compare the string literal 'random' to subquery that will never ever return this value. In the where clause you cannot filter on a calculated field because the select list is evaluated after the where clause. You can only filter on such fields in the having clause and remove the speechmarks atound the word random:

SELECT
CONCAT(
    FLOOR( (RAND() * ( {$this->_maxColumns} - 1 + 1 ) ) + 1 ),
    '-',
    FLOOR( (RAND() * ( {$this->_maxRows} - 1 + 1 ) ) + 1 )
) as random

FROM `grid`

HAVING random NOT IN (
    SELECT CONCAT( `x`, '-', `y` ) FROM `grid`
)

However, it is possible that the above query will not return any rows at all. I would rather generate a list of non-existing coordinates within a range and randomly choose one of them. I would have a helper table with all possible x - y pairs, just do a left join on the grid table with is null in the where criteria and either use order by rand() limit 1, or do the random selection from php.

Comments