【问题标题】:Iterating through PHP array with duplicate records and deleting one record where a value = 0遍历具有重复记录的 PHP 数组并删除值 = 0 的一条记录
【发布时间】:2014-10-22 21:31:32
【问题描述】:

我有一个使用 Laravel 的 MySQL 查询,我将其转换为 PHP 数组。

行的值与此类似:

name | override | percentage
Eclipse | 1 | 50%
Eclipse | 0 | 75%

MySQL 查询

select * from table

两行(实际上不止 2 行)具有相同的名称,但其中一个将 override 设置为 0,一个将其设置为 1。

如何删除查询结果(PHP 数组)中所有重复(由名称确定)且覆盖设置为 0 的记录?我只想要已被我所做的新记录覆盖的记录,但我需要一种方法来删除覆盖 = 0 的记录,因为这些记录是相同的但具有不同的百分比值。

如何做到这一点?

谢谢。

【问题讨论】:

  • 你为什么不直接在你的 MySQL 查询中做呢?这样你就可以用 PHP 得到好的结果
  • 如何在 MySQL 中做到这一点?
  • 考虑到复杂性,我认为它需要一些数组操作才能做到这一点。
  • 用你当前的 MySQL 查询更新你的问题
  • @JustinIurman 好的,哈哈。完毕。实际上它要大得多。该查询有大约 10 个连接,并且正在选择数百条记录。我只是用上面的例子。这是相同的概念,但我只是提供了上面的列行以简化解释。

标签: php mysql sql arrays laravel


【解决方案1】:

尝试以下查询,

SELECT * from testtable GROUP BY `name` HAVING count(`name`) = 1 OR `override` = 1;

检查这个sqlfiddle

【讨论】:

  • 这仅显示 override = 1 的记录。
  • 请检查sqlfiddle,它还显示覆盖= 0的记录,第二条记录记事本覆盖= 0
  • 好的,我知道我已将此添加到我的查询中,现在它不会返回任何具有重复名称的记录。
  • 你的意思是说,如果 Eclipse 有 3 条记录,一条 override=1,两条 override=0,然后返回 2 条记录,一条 override=1,一条 override=0,而不是三个记录?
  • 在这种情况下,你应该把你的原始查询放在这里,因为你可以检查它在那里工作的 sqlfiddle 意味着它也应该为你工作,如果它不工作那么这意味着有问题您正在测试的查询
【解决方案2】:

注意:在 SQL 中执行此操作会更快 WAYYYYYYYYY 并且使用更少的内存。如果您由于某种原因无法修改 SQL,我只会尝试这种 PHP 方法。

也许可以尝试...两次访问数据库,第一次只获得非覆盖,然后在第二遍获得覆盖——强制您的数组按名称索引并 array_merge 它们。 (考虑到数组和副本的数量,使用相当大的内存 - 但它很容易理解并保持简单。

$initial = get_non_overridden();
$override = get_overridden();
$init_indexed = index_by_name($initial);
$over_indexed = index_by_name($override);

$desired_result = array_merge($init_indexed, $over_indexed);

假设您的数据库为您提供了一个标准行集(行数组,其中每一行是字段的哈希值->值)。我们想要看起来像这样的东西:

[
  'Eclipse' => [
    'name' => 'Eclipse',
    'override' => '0',
    'percentage' => '75%'
  ],
  'Something' => [
    'name' => 'Something',
    'override' => '0',
    'percentage' => '20%'
  ],
]

所以 index_by_name 将是:

function index_by_name($rowset) {
  $result = array();
  foreach ($rowset as $row) {
    $result[ $row['name'] ] = $row;
  }
  return $result;
}

有一些方法可以在内存或运行时调整您的效率,但这是我所想的要点。

array_merge 然后用覆盖的覆盖初始的。

注意:这一切都假设只有一行 Eclipse 覆盖为 1。如果您有 20 个 Eclipse|0 和一个 Eclipse|1,这将起作用,如果您有两个 Eclipse|1,您只会看到一个其中...没有办法说是哪一个。

【讨论】:

  • index_by_name 函数应该做什么?
  • 选择这个作为答案,因为它解决了我的问题,而其他的没有。
【解决方案3】:

如果我正确理解您的需求,您需要过滤掉重复名称和override = 0 的记录。

如果您按name (SELECT * FROM TABLE ORDER BY name) 对结果集进行排序,则可以使用此功能。

function removeDuplicatesFromArray($rows) {
    $result = array();
    $old_name = '';
    foreach($rows as $row) {
        if($row['name'] != $old_name) {
            $result[] = $row;
            $old_name = $row['name'];
        }
        elseif($row['override'] == 1) {
            array_pop($result);
            $result[] = $row;             
        }       
    }
    return $result; 
}

【讨论】:

    猜你喜欢
    • 2011-08-18
    • 1970-01-01
    • 2018-02-17
    • 2013-04-23
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多