【问题标题】:loop within a loop for updating db record在循环内循环更新数据库记录
【发布时间】:2012-12-30 08:39:37
【问题描述】:

我有一个包含以下数据的交易表:

dealID   |   date    |   followUP  |  user
1        |2012-10-15 |    Yes      |
2        |2012-12-24 |    Yes      |
3        |2013-01-05 |             |
4        |2013-02-02 |    Yes      |
5        |2013-02-02 |    Yes      |

还有一个包含我的用户列表的用户表

userID    | name
1         | john
2         | eric
3         | anne

我想做的是查询第一个将 followUP 设置为“YES”的表,然后从结果中从 users 表中按顺序为他们分配一个用户,这样我的最终交易表将如下所示

dealID   |   date    |   followUP  | userID
1        |2012-10-15 |    Yes      | 1
2        |2012-12-24 |    Yes      | 2
3        |2013-01-05 |             |
4        |2013-02-02 |    Yes      | 3
5        |2013-02-02 |    Yes      | 1

我知道它是一个循环,但由于某种原因,我无法弄清楚如何设置第二个循环来分配用户的价值。任何帮助将不胜感激。

【问题讨论】:

  • 您将如何决定将哪个用户分配给哪个交易?您在交易表中没有任何用户 ID?
  • 您希望根据userID按顺序将用户分配到具有followUP = 'Yes'的交易?
  • 现在只需将 userID 按顺序分配给 users 表。到目前为止,我唯一能做的就是更新交易表,但仅限于一个用户,我无法弄清楚如何在交易更新查询也在循环时循环 userID。
  • 那么,你在“user”表中的userID不是自动增量的??
  • 我的ID都是AI。是的,我想根据用户 ID 按顺序更新 followUP = 'Yes' 的交易表

标签: php mysql loops


【解决方案1】:

首先将您的用户 ID 放入一个数组中以使其看起来:

$uids = array(1, 2, 3);

然后,当从交易表中读取记录时,像这样编写更新查询:

$follow_up_user_idx = 0;
$update_queries = array();
while($row=mysqli_fetch_assoc($result)) {
    // ... do whatever you need to
    if($row['followUP'] != 'Yes') continue;
    $update_queries[] = "UPDATE `deals` SET `user` = '" . $uids[$follow_up_user_idx] . "'
                         WHERE `dealID` = '" . $row['dealID'] . "' LIMIT 1";
    $follow_up_user_idx++;
    if($follow_up_user_idx > count($uids) - 1) $follow_up_user_idx = 0;
}

现在您有了所有更新查询。只需执行它们:

foreach($update_queries as $uq) {
    mysqli_query($link, $uq);
}

【讨论】:

    【解决方案2】:

    您必须按照一系列步骤来实现您所提到的。

    1) 从数据库中获取所有followUP 为“是”的记录。
    假设第一个表是deals。因此,获取所有 followUP 为“是”的记录。
    可以说,您有 $deals_details 的结果。

    2) 从数据库中获取所有用户(名称)。
    假设第二张桌子是users。所以,获取所有用户。
    假设您在 $users_details 数组中拥有所有用户的姓名。
    在单独的变量中获取系统中的总用户数,例如 $users_count。

    3) 循环访问 $deals_details 并从 $users_details 依次为每个用户分配。

    $i = 0;
    foreach($deals_details as $keyDD => $valueDD){
        $user = $users_details[$i];
        $i++;
        if($i == $users_count)
            $i = 0;
        $query = "update `deals` set user = '".$user."' where dealID = '".$valueDD['dealID']."'";
    
        //fire query
        //$link is connection variable.
        mysqli_query($link, $query);
    }
    

    【讨论】:

      【解决方案3】:

      这可能是一个糟糕的设计决策。在不了解您的应用程序的更多信息的情况下,我很想等待用户可用/请求交易,然后(从队列中)分配给他们(从队列中)需要跟进的下一个交易。即使您有充分的理由在用户“可用”之前分配用户,您也可以考虑在基于某些适当业务逻辑的交易创建/修改时这样做(例如,维护要分配给下一个交易的用户队列)。

      确实,使用简单的UPDATE 语句执行此操作并没有特别好的方法。纯粹在数据库中完成它的一种方法是使用存储过程(尽管它不是特别安全的并发,因为在关闭和重新打开 _curUser 游标之间更改 Users 表可能会导致不良影响;可能会改为出于此过程的目的,将Users 复制到临时表中,具体取决于您所需的逻辑):

      DELIMITER //
      
      CREATE PROCEDURE assignDeals() BEGIN
        DECLARE _userID, _dealID BIGINT UNSIGNED;
        DECLARE _done BOOLEAN DEFAULT FALSE;
      
        DECLARE _curUser CURSOR FOR
          SELECT   userID
          FROM     users
          ORDER BY userID;
      
        DECLARE _curDeal CURSOR FOR
          SELECT   dealID
          FROM     deals
          WHERE    followUP = 'Yes'
          ORDER BY dealID
          FOR UPDATE;
      
        DECLARE CONTINUE HANDLER FOR NOT FOUND
          SET _done := TRUE;
      
        PREPARE stmt FROM 'UPDATE deals SET userID = ? WHERE dealID = ?';
      
        OPEN _curUser;
        OPEN _curDeal;
      
        readDeal: LOOP
          FETCH _curDeal INTO _dealID;
          IF _done THEN
            LEAVE readDeal;
          END IF;
      
          FETCH _curUser INTO _userID;
          IF _done THEN
            SET _done := FALSE;
            CLOSE _curUser;
            OPEN  _curUser;
            FETCH _curUser INTO _userID;
            IF _done THEN
              SIGNAL SQLSTATE VALUE '45000' SET
                MESSAGE_TEXT = 'No users';
              LEAVE readDeal;
            END IF;
          END IF;
      
          SET @userID := _userID, @dealID := _dealID;
          EXECUTE stmt USING @userID, @dealID;
        END LOOP readDeal;
      
        CLOSE _curUser;
        CLOSE _curDeal;
      
        DEALLOCATE PREPARE stmt;
      END//
      
      DELIMITER ;
      

      在sqlfiddle 上查看。

      【讨论】:

        【解决方案4】:

        表用户 +---------------+---------------+------------+ |用户 ID |用户名 |用户级别 | +---------------+---------------+------------+ | 1 |超级管理员 |管理员 | | 2 |副管理员 |管理员 | | 3 |团队1 |团队 | | 4 |团队2 |团队 | | 5 |团队3 |团队 | | 6 |客户1 |客户 | | 7 |客户2 |客户 | | 8 |客户3 |客户 | | 9 |客户4 |客户 | +---------------+---------------+------------+ 餐桌投诉: +---------------+---------------+------------+ |投诉ID |投诉 |用户 ID | +---------------+---------------+------------+ | 1 |操作系统问题 | 7 | | 2 | USB 问题 | 8 | | 3 |操作系统currepted | 7 | | 4 |高清问题 | 9 | | 5 | DVD发行| 6 | | 6 |软件问题 | 9 | | 7 |网络问题| 9 | | 8 |系统问题 | 6 | +---------------+---------------+------------+ 表assign_work +---------------+------------+ |投诉ID |用户 ID | +---------------+------------+ | 1 | 3 | | 2 | 4 | | 3 | 5 | | 4 | 3 | | 5 | 4 | | 6 | 5 | | 7 | 3 | | 8 | 4 | +---------------+------------+

        当客户提出投诉时,投诉数据也应保存在最后一个投诉表中 投诉 ID 应同时保存在 assign_work 表中
        user_id 也按顺序保存,从用户表中获取只有该人员 ID 的团队。 我是 ph 新手,请任何人帮助我。

        【讨论】:

          猜你喜欢
          • 2010-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-07
          相关资源
          最近更新 更多