Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP从数据库中随机选择一行,但不要选择相等的行_Php_Mysql_Database_Arrays - Fatal编程技术网

使用PHP从数据库中随机选择一行,但不要选择相等的行

使用PHP从数据库中随机选择一行,但不要选择相等的行,php,mysql,database,arrays,Php,Mysql,Database,Arrays,我的问题几乎是不言自明的,但我无法尽可能地解决它。 我想从MySQL数据库中随机选择一个条目。我希望它尽可能快,尽可能高效(这一直是目标,不是吗?)。当我选择该行时,我想选择另一行,但与前面的行不同。如果我选择10行,我希望第11行与所有其他行不同(比如说唯一:)。但当我的行数用完时,我想“报告一个错误” 找到问题的核心。我正在使用PHP和MySQL。我有一个输入数组,其中包含已选定的标题。然后我得到数据库中所有项目的计数,这样我就知道我可以“循环max”多少次。让我们粘贴代码,看看我们在处理什

我的问题几乎是不言自明的,但我无法尽可能地解决它。
我想从MySQL数据库中随机选择一个条目。我希望它尽可能快,尽可能高效(这一直是目标,不是吗?)。当我选择该行时,我想选择另一行,但与前面的行不同。如果我选择10行,我希望第11行与所有其他行不同(比如说唯一:)。但当我的行数用完时,我想“报告一个错误”

找到问题的核心。我正在使用PHP和MySQL。我有一个输入数组,其中包含已选定的标题。然后我得到数据库中所有项目的计数,这样我就知道我可以“循环max”多少次。让我们粘贴代码,看看我们在处理什么

try
{
    $db = new PDO("mysql:host=localhost;dbname=xxxxx;charset=utf8", "xxxx", "xxxx");

    $played = explode(":;:", $_POST['items']); //All already selected items are in $_POST separated by :;:

    $sql = "SELECT count(id) AS count FROM table"; //Lets get the total count of items

    $query = $db->prepare($sql);
    $query->execute();
    $result = $query->fetch(PDO::FETCH_ASSOC);

    $count = $result['count']; //There we are...
    $i = 0; //Index counter so we dont exceed records.. well kinda (more on that below)

    do //do while because we want something to be selected first
    {
        $sql = "SELECT FLOOR(RAND() * COUNT(*)) AS offset FROM table"; //From here

        $query = $db->prepare($sql);
        $query->execute();
        $result = $query->fetch(PDO::FETCH_ASSOC);
        $offset = $result['offset'];

        $sql = "SELECT itemXML FROM table LIMIT $offset, 1";

        $query = $db->prepare($sql);
        $query->execute();
        $result = $query->fetch(PDO::FETCH_ASSOC); //To here is some code to randomly select a record "as efficiently as possible"..

        $output = Array();

        $xml = simplexml_load_string($result['itemXML']);

        $i++;
    } while (in_array($xml->{"title"}, $played) && $i < $count); //While record title is in array and while we have not exceeded the total number of records (that's the logic but it isint that simple is it?)

    if ($i >= $count)
    {
        die("400"); //Just a random status code which I parse with the client.
    }

    $itemArr = Array("whatever" => $xml->{"whatever-attr"}, "title" => $xml->{"title"});
    array_push($output, $itemArr); Lets push this to out array

    echo json_encode($output); //Aaaaand finally lets print out the results
}
catch (Exception $e) //If anything went wrong lets notify our client so he can respond properly
{
    $output = Array("error" => $e->getMessage());
    die(json_encode($output));
}
试试看
{
$db=newpdo(“mysql:host=localhost;dbname=xxxxx;charset=utf8”、“xxxx”、“xxxx”);
$played=explode(“:;:”,$\u POST['items']);//所有已选择的项目都在$\u POST中,以:;:
$sql=“选择count(id)作为表中的计数”;//让我们获取项目的总计数
$query=$db->prepare($sql);
$query->execute();
$result=$query->fetch(PDO::fetch_ASSOC);
$count=$result['count'];//我们到了。。。
$i=0;//索引计数器,这样我们就不会超过记录。。嗯,有点(下面有更多内容)
do//do while,因为我们希望先选择某个对象
{
$sql=“选择楼层(RAND()*COUNT(*)作为表的偏移量”;//从这里开始
$query=$db->prepare($sql);
$query->execute();
$result=$query->fetch(PDO::fetch_ASSOC);
$offset=$result['offset'];
$sql=“从表中选择itemXML限制$offset,1”;
$query=$db->prepare($sql);
$query->execute();
$result=$query->fetch(PDO::fetch_ASSOC);//这里有一些代码,可以“尽可能有效地”随机选择一条记录。。
$output=Array();
$xml=simplexml_load_string($result['itemXML']);
$i++;
}while(在数组中($xml->{“title”},$played)&&&$i<$count);//当记录标题在数组中并且我们没有超过记录总数时(这是逻辑,但它不是那么简单,是吗?)
如果($i>=$count)
{
die(“400”);//只是一个随机状态码,我用客户端解析它。
}
$itemArr=Array(“whatever”=>$xml->{“whatever attr”},“title”=>$xml->{“title”});
array\u push($output,$itemArr);让我们将其推出数组
echo json_encode($output);//aaaa最后让我们打印出结果
}
catch(异常$e)//如果出现任何问题,让我们通知我们的客户,以便他能够正确响应
{
$output=Array(“错误”=>$e->getMessage());
die(json_编码($output));
}
是的,嗯。。问题是,如果有10条记录,选择了9行,索引计数器
$i
变大或等于10,并且随机记录都在数组中,该怎么办。然后我们有一行应该被选中,但它不是

我该如何解决这个问题?非常感谢您的帮助

如果我解释得不够好,请让我知道,我会更加努力。

我认为你在这里采取了错误的方法。您不需要在数据库中循环,一次查询一条记录

如果需要选择10条记录,只需选择10条按RAND()排序的记录,如下所示

SELECT * FROM table
ORDER BY RAND()
LIMIT 10;
或者如果您有要从选择中忽略的特定ID

SELECT * FROM table
WHERE id NOT IN (?, ?, ?, ...)
ORDER BY RAND()
LIMIT 10;
或者如果要忽略的id存储在另一个表中

SELECT * FROM table
LEFT OUTER JOIN omit_table ON table.id = omit_table.id
WHERE omit_table.id IS NULL
ORDER BY RAND()
LIMIT 10;

我认为你在这里采取了错误的方法。您不需要在数据库中循环,一次查询一条记录

如果需要选择10条记录,只需选择10条按RAND()排序的记录,如下所示

SELECT * FROM table
ORDER BY RAND()
LIMIT 10;
或者如果您有要从选择中忽略的特定ID

SELECT * FROM table
WHERE id NOT IN (?, ?, ?, ...)
ORDER BY RAND()
LIMIT 10;
或者如果要忽略的id存储在另一个表中

SELECT * FROM table
LEFT OUTER JOIN omit_table ON table.id = omit_table.id
WHERE omit_table.id IS NULL
ORDER BY RAND()
LIMIT 10;

假设您已经在下表中填入了数据:

TABLE mydata
  id INT AUTOINCREMENT PRIMARYKEY
  name VARCAHAR
  ...
我们为一些非随机映射创建下表:

TABLE shufflemap
  id INT AUTOINCREMENT PRIMARYKEY
  data_id INT UNIQUEINDEX
我们做了以下工作:

$rs = $dbh->query('SELECT id FROM mydata');
shuffle($rs);
foreach($rs as $data_id) {
    $dbh->query('INSERT INTO shufflemap (data_id) VALUES (?)', array($data_id));
}
现在,如果我们想添加行呢?您可以
截断表并重新运行上述代码,或者:

$my_new_id = 1234; //the ID of the new row inserted into `mydata`
$rs = $dbh->query('SELECT COUNT(*) AS 'count' from shufflemap');
$target = rand(0,$rs[0]['count']);
$rs = $dbh->query('SELECT id, data_id FROM shufflemap LIMIT ?,1', array($target));
$swap_id = $rs[0]['id'];
$swap_data_id = $rs[0]['data_id'];
$dbh->query('UPDATE shufflemap SET data_id = ? WHERE id = ?', array($my_new_id, $swap_id));
$dbh->query('INSERT INTO shufflemap (data_id) VALUES (?)', array($swap_data_id));
它以合理有效的方式从shufflemap表中选取随机条目,用新的替换数据_id,并将旧的固定到表的末尾

使用这种方式,您可以获得看似随机的数据,而无需重复,并且仍然可以通过在联接、子查询或其他任何您能想到的方法中使用shufflemap表来使用表中所有适当的索引

编辑 假设mydata表有一个字段,指示每个字段与哪个客户机或用户关联,即:

TABLE mydata
  id INT AUTOINCREMENT PRIMARYKEY
  client_id INT
  name VARCAHAR
  ...
只能通过以下方式检索该客户机数据的无序列表:

SELECT d.*
FROM mydata d INNER JOIN shufflemap s
  ON d.id = s.data_id
WHERE client_id = ?
ORDER BY s.id
是否排除已播放项目的列表

SELECT d.*
FROM mydata d INNER JOIN shufflemap s
  ON d.id = s.data_id
WHERE client_id = ?
  AND d.id NOT IN(?,?,?,...)
ORDER BY s.id

假设您已经在下表中填入了数据:

TABLE mydata
  id INT AUTOINCREMENT PRIMARYKEY
  name VARCAHAR
  ...
我们为一些非随机映射创建下表:

TABLE shufflemap
  id INT AUTOINCREMENT PRIMARYKEY
  data_id INT UNIQUEINDEX
我们做了以下工作:

$rs = $dbh->query('SELECT id FROM mydata');
shuffle($rs);
foreach($rs as $data_id) {
    $dbh->query('INSERT INTO shufflemap (data_id) VALUES (?)', array($data_id));
}
现在,如果我们想添加行呢?您可以
截断表并重新运行上述代码,或者:

$my_new_id = 1234; //the ID of the new row inserted into `mydata`
$rs = $dbh->query('SELECT COUNT(*) AS 'count' from shufflemap');
$target = rand(0,$rs[0]['count']);
$rs = $dbh->query('SELECT id, data_id FROM shufflemap LIMIT ?,1', array($target));
$swap_id = $rs[0]['id'];
$swap_data_id = $rs[0]['data_id'];
$dbh->query('UPDATE shufflemap SET data_id = ? WHERE id = ?', array($my_new_id, $swap_id));
$dbh->query('INSERT INTO shufflemap (data_id) VALUES (?)', array($swap_data_id));
它以合理有效的方式从shufflemap表中选取随机条目,用新的替换数据_id,并将旧的固定到表的末尾

使用这种方式,您可以获得看似随机的数据,而无需重复,并且仍然可以通过在联接、子查询或其他任何您能想到的方法中使用shufflemap表来使用表中所有适当的索引

编辑 假设mydata表有一个字段,指示每个字段与哪个客户机或用户关联,即:

TABLE mydata
  id INT AUTOINCREMENT PRIMARYKEY
  client_id INT
  name VARCAHAR
  ...
只能通过以下方式检索该客户机数据的无序列表:

SELECT d.*
FROM mydata d INNER JOIN shufflemap s
  ON d.id = s.data_id
WHERE client_id = ?
ORDER BY s.id
是否排除已播放项目的列表

SELECT d.*
FROM mydata d INNER JOIN shufflemap s
  ON d.id = s.data_id
WHERE client_id = ?
  AND d.id NOT IN(?,?,?,...)
ORDER BY s.id

为什么不一次选择所有需要的记录并随机排序?选择随机数据