按列值对多行结果集数据进行分组

Group multiples rows of result set data by a column value

我想将分配给特定员工的逾期任务作为电子邮件摘要发送。多个待办事项可能分配给同一个员工。因此可以将多个待办事项分配给同一名员工并且已过期。这就是问题开始的地方...

所以我所做的是从数据库中抓取所有逾期任务,然后抓取分配给任务的员工。我创建了一个由 todoIDemployeeIDemployeeEmail 组成的数组。现在,是否有更好的方法来执行此操作,如果没有,我如何按电子邮件地址对行进行分组?

最终结果应该是一个数组,显示分配给一名员工的每个逾期待办事项。

// Get all Todos that are not archived

$sql = "SELECT * FROM todo WHERE archiv = 0";
$abfrage = $db->prepare($sql);
$abfrage->execute();

$overdue_array = array();

// Now we get everything that's overdue from the Database
while ($row = $abfrage->fetch()) {

    if ($row["status"] !== 3) {
        if ($row["archiv"] !== 1) {
            if ($row["durchfuehrung"]) {
                if (strtotime($row["durchfuehrung"]) < strtotime(date("Y-m-d"))) {
                
                    // Here we now get the email from the assiged employee to the todo
                    
                    $sql2 = "SELECT email FROM mitarbeiter WHERE mitarbeiterID = :mitarbeiterFID";
                    $abfrage2 = $db->prepare($sql2);
                    $abfrage2->bindParam("mitarbeiterFID", $row["mitarbeiterFID"]);
                    $abfrage2->execute();

                    while ($row2 = $abfrage2->fetch()) {
                        $overdue_array[] = array("todoID" => $row["todoID"], "mitarbeiterID" => $row["mitarbeiterFID"], "mitarbeiterEmail" => $row2["email"]);
                    }
                }
            }
        }
    }

结果如下:

您可以通过 JOIN(如@mickmackusa 所说)强烈改进您的请求,甚至可以使用 PDO Fetch Statements(例如 PDO FETCH_GROUPPDO 获取关联)。您可以通过一个(更大但更好的)请求直接获得您想要的结果。

然而,如果您只想使用 PHP 对数组进行排序,使用 foreach 可以完成这项工作。

foreach ($array as $todo) {

    if (!isset($newArray[$todo["mitarbeiterEmail"]])) {

        // Here we create a new array with the email as a key and put the two first key-values in it with array_slice
        $newArray[$todo["mitarbeiterEmail"]] = [array_slice($todo, 0, 2)];

    } else {

        // Here we push another todo if the email is already declared as a key
        array_push($newArray[$todo["mitarbeiterEmail"]], array_slice($todo, 0, 2));

    }

}

// Check your new array
print_r($newArray);

您还可以通过组合 array_multisort to sort by emails then array_reduce 删除保留关联数据的重复元素来避免 foreach。可以提出很多解决方案。

让我们用一些最佳实践来完善您的脚本...

  • 仅在需要时向 SELECT 子句添加列
  • 享受 PDO 非常方便的抓取模式 -- FETCH_GROUP 非常适合您的情况。
  • 始终努力减少访问数据库的次数
  • 始终尽量减少使用的循环次数。

推荐代码(没错,就是这么简单):

$sql = "SELECT email, todoID, mitarbeiterFID
        FROM todo 
        JOIN mitarbeiter ON mitarbeiterID = mitarbeiterFID
        WHERE archiv = 0
          AND status != 3
          AND durchfuehrung < CURRENT_DATE";
foreach ($db->query($sql)->fetchAll(PDO::FETCH_GROUP) as $email => $rows) { 
    sendSummary($email, $rows, $company, $db);
}

郑重声明,我不知道$company来自哪里。