You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:获取指定交易类型的员工最新交易详情实现方案

问题:获取员工指定类型的最新交易详情

需求说明

要获取所有员工中,交易类型为Add、Update、Read的最新交易详情,注意:如果员工最后一笔交易是Delete(不在指定范围内),则不纳入结果。

样例数据表

employees表

employee_idemployee_name
1John Doe
2Jane Doe
3Teri Dactyl
4Allie Grater

transactions表

transaction_idemployee_idtransaction_datetransaction_typeremarks
112021-03-28Addtest 1
232022-09-07Addtest 2
322019-08-01Addtest 3
442023-06-05Readtest 4
542023-05-12Addtest 5
622020-02-01Readtest 6
732022-11-15Updatetest 7
812020-06-14Addtest 8
912020-01-14Updatetest 9
1022023-12-31Deletetest 10

期望输出

Transaction IDEmployee NameTransaction DateTransaction TypeRemarks
4Allie Grater2023-06-05Readtest 4
7Teri Dactyl2022-11-15Updatetest 7
1John Doe2021-03-28Addtest 1

注:Jane Doe不在结果中,因其最后一笔交易类型为Delete,不属于指定的[Add, Update, Read]范围。

当前代码(PHP)

<?php

$transaction_types = ['Add', 'Update', 'Read'];

$output = '';

$query = "SELECT * FROM transactions 
          INNER JOIN employees ON employees.employee_id = transactions.employee_id 
          WHERE transactions.transaction_type IN ('".implode("', '", $transaction_types)."') 
          GROUP BY transactions.employee_id 
          ORDER BY DATE(transactions.transaction_date) DESC
          ";
$stmt = $connect->prepare($query);
if ($stmt->execute()) {
   if ($stmt->rowCount() > 0) {
      $output .= '<table>
                    <thead>
                       <tr>
                          <th>Transaction ID</th>
                          <th>Employee Name</th>
                          <th>Transaction Date</th>
                          <th>Transaction Type</th>
                          <th>Remarks</th>
                       </tr>
                    </thead>
                    <tbody>';
      $result = $stmt->fetchAll();
      foreach ($result as $row) {
         $output .= '<tr>
                        <td>'.$row->transaction_id.'</td>
                        <td>'.$row->employee_name.'</td>
                        <td>'.$row->transaction_date.'</td>
                        <td>'.$row->transaction_type.'</td>
                        <td>'.$row->remarks.'</td>
                     </tr>';
      }
      $output .= '</tbody></table>';
   }
}

echo $output;

?>

问题分析与修正方案

当前代码的SQL存在两个核心问题:

  1. GROUP BY逻辑错误:直接按employee_id分组后,SELECT *会返回每组的第一条数据(而非最新交易),不符合需求。
  2. 未过滤最后一笔交易为Delete的员工:当前WHERE条件只筛选了指定类型的交易,但员工可能有后续的Delete交易,这类员工应该被排除。

修正后的SQL逻辑

先找出每个员工的最新交易日期,判断该交易是否属于指定类型;如果是,再关联获取该交易的详情。

修正后的SQL语句:

SELECT 
    t.transaction_id,
    e.employee_name,
    t.transaction_date,
    t.transaction_type,
    t.remarks
FROM transactions t
INNER JOIN employees e ON e.employee_id = t.employee_id
INNER JOIN (
    -- 子查询获取每个员工的最新交易日期
    SELECT employee_id, MAX(transaction_date) AS latest_date
    FROM transactions
    GROUP BY employee_id
) latest_t ON t.employee_id = latest_t.employee_id AND t.transaction_date = latest_t.latest_date
-- 只保留最新交易属于指定类型的记录
WHERE t.transaction_type IN ('Add', 'Update', 'Read')
ORDER BY t.transaction_date DESC;

修正后的PHP代码

<?php

$transaction_types = ['Add', 'Update', 'Read'];

$output = '';

// 使用参数绑定避免SQL注入
$query = "SELECT 
            t.transaction_id,
            e.employee_name,
            t.transaction_date,
            t.transaction_type,
            t.remarks
          FROM transactions t
          INNER JOIN employees e ON e.employee_id = t.employee_id
          INNER JOIN (
              SELECT employee_id, MAX(transaction_date) AS latest_date
              FROM transactions
              GROUP BY employee_id
          ) latest_t ON t.employee_id = latest_t.employee_id AND t.transaction_date = latest_t.latest_date
          WHERE t.transaction_type IN (:types)
          ORDER BY t.transaction_date DESC";

// 处理数组参数绑定,适配PDO
$typesStr = implode(',', array_fill(0, count($transaction_types), '?'));
$query = str_replace(':types', $typesStr, $query);
$stmt = $connect->prepare($query);
$stmt->execute($transaction_types);

if ($stmt->rowCount() > 0) {
    $output .= '<table>
                  <thead>
                     <tr>
                        <th>Transaction ID</th>
                        <th>Employee Name</th>
                        <th>Transaction Date</th>
                        <th>Transaction Type</th>
                        <th>Remarks</th>
                     </tr>
                  </thead>
                  <tbody>';
    $result = $stmt->fetchAll(PDO::FETCH_OBJ);
    foreach ($result as $row) {
        $output .= '<tr>
                        <td>'.$row->transaction_id.'</td>
                        <td>'.$row->employee_name.'</td>
                        <td>'.$row->transaction_date.'</td>
                        <td>'.$row->transaction_type.'</td>
                        <td>'.$row->remarks.'</td>
                     </tr>';
    }
    $output .= '</tbody></table>';
}

echo $output;

?>

关键改进点

  • 用子查询先获取每个员工的最新交易日期,确保只筛选该日期的交易;
  • 通过WHERE条件排除最新交易为Delete的员工;
  • 使用参数绑定避免SQL注入风险(原代码直接拼接字符串存在注入隐患);
  • 明确指定SELECT字段,避免GROUP BY或JOIN时的字段冲突。

内容的提问来源于stack exchange,提问作者Mr.Jepoyyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:52:54