0

我很惊讶还没有答案……这表明我在做一些根本错误的事情。或者其他人都是。

假设我有一个可能重复的值数组,这些值在客户端作为 POST 请求进入,目标是从 MySQL 返回一个由这些值索引的结果集,并且与这些值的顺序相同,并保留冗余!!!

因此,如果值为:1,2,3,2,3,4,5,5,5

期望的结果是:

+----+-------+
| id | value |
+----+-------+
|  1 | one   |
|  2 | two   |
|  3 | three |
|  2 | two   |
|  3 | three |
|  4 | four  |
|  5 | five  |
|  5 | five  |
|  5 | five  |
+----+-------+

下面的代码似乎有效,但天哪,认真的吗?我必须滥用array_intersect()并且有两个不同的循环,其中一个是嵌套的,只是为了使一个简单的结果集得到排序并以与输入数组相同的模式重复?这不可能是真正应该做到的。

function repQuery($inids,$incol,$querystring,$emptyval = "NULL"){
    # incol is the name of a column in the query
    # inids is an array within which the value of incol must be found
    # querystring is a query of the form...
    # "select FOO from BAR where %s in (%s) BLAH BLAH BLAH"
    # The first %s will be replaced by $incol and the second by $inids
    $qq = mysql_query(sprintf($querystring,$incol,implode(",",$inids))) or die(mysql_error());
    $nf = mysql_num_fields($qq); $dummyrow = array();
    for($ii = 0; $ii < $nf; $ii+= 1){
        $dummyrow[mysql_field_name($qq,$ii)] = $emptyval;
    };
    $out = array_fill(0,count($inids),$dummyrow);
    while($rr = mysql_fetch_assoc($qq)){
        foreach(array_keys(array_intersect($inids,array($rr[$incol]))) as $ii) {
            $out[(int)$ii] = $rr;
        }
    }
    return $out;
}

我的问题是:是否有一些可接受的模式或 PHP 数组命令或其他我忽略的东西?在R上面将是一个单行。

4

2 回答 2

1

虽然如果它是 MySQL 中的一个功能会很棒,但我认为没有一种方法可以使用ORDER BY重复模式(你可以通过 获得“自定义模式” ORDER BY FIELD(),但不完全在那里)。

我不确定 PHP 中是否有任何特殊方法,但使用临时数组可能会减轻头痛:

function repQuery($inids,$incol,$querystring,$emptyval = "NULL"){
    $qq = mysql_query(sprintf($querystring,$incol,implode(",",$inids))) or die(mysql_error());

    // build a temporary array of all of the results - the row's "ID" is the array index
    $tmpResults = array();
    while ($row = mysql_fetch_assoc($qq)) {
        $tmpResults[$row['id']] = $row;
    }

    // iterate through the order/list of IDs and insert each result one after the other
    $out = array();
    foreach ($inids as $id) {
        $out[] = $tmpResults[$id];
    }
    return $out;
}

$tmpResults这将使用行的 ID 作为数组的索引将每个 SQL 结果(每个 ID 一个)放入数组中。下一步是遍历$inids包含要复制的模式的列表,并将相应的记录结果插入到$out数组中。

于 2012-08-17T22:35:35.177 回答
0

我使用 PDO 并使用下面的 PDO 从数据库中获取数据。因此,如果您出于某种原因对通过 PDO 获取数据不感兴趣,请不要费心阅读。(我使用 PDO 时不熟悉 mysql_* 命令。)

如果是我,我会在传递给 MySQL 之前使 $inids 唯一(array_unique)并更改 SQL 语句以在 SELECT 语句中包含 ID。就像是:

select %s, FOO from BAR where %s in (%s)

然后 sprintf 变成

$tempIds = array_unique($inids);
sprintf($querystring,$incol,$incol,implode(",",array_unique($tempIds)))

PDO 将类似于

$db->prepare(sprintf($querystring,$incol,$incol,implode(",",$tempIds)));
$db->execute(array());
$results = $db->fetchAll();

所以对于你的组织结构,我会使用这样的东西:

$ids = array();
$srch = array();
foreach ($results AS $key=>$dbData) {
  $ids[] = $dbData['ID'] . ":" . $dbData['FOO'];
  $srch[] = (string) $dbData['ID'];
} 

$out = str_replace($srch, $ids, $inids);

我想有更好的方法可以做到这一点,但我还没有想出它。假设 $inids 是一个像这样的数组,这应该可以工作:

$inids = array('1', '2', ...);

如果这些值不是字符串,那么它们需要在传递给 str_replace 之前转换为字符串。然后,当您想将它们输出到您的页面或某处时,您可以这样做:

foreach ($out AS $key=>$str) {
$data = explode(':', $str);
  echo '<br>' . $data[0] . \t . '|' . \t . $data[1];
}

随心所欲地使用 echo 语句。

于 2012-08-17T23:44:24.017 回答