Php 多查询字符串中的SQL MAX()

Php 多查询字符串中的SQL MAX(),php,sql,mysql,Php,Sql,Mysql,我有一个由3个查询组成的字符串,用于 查找哪些邮件具有表示答复的相同id的其他邮件 查找来自第一个查询的结果的哪些消息具有指定的用户,以输入该消息字符串的第一条消息(最小时间戳) 查找该消息字符串的最新消息(最大时间戳) 问题来自第三个查询。在第二个查询之前,我得到了预期的结果,然后在执行第三个查询时,没有MAX(timestamp)作为MAX,我得到了预期的结果。当我添加它时,我只会在每个消息字符串应该是最后一个消息时获得第一个消息,而不管我使用的是最小还是最大,并且当显示2行时,行计数表示返

我有一个由3个查询组成的字符串,用于

  • 查找哪些邮件具有表示答复的相同id的其他邮件
  • 查找来自第一个查询的结果的哪些消息具有指定的用户,以输入该消息字符串的第一条消息(最小时间戳)
  • 查找该消息字符串的最新消息(最大时间戳)
  • 问题来自第三个查询。在第二个查询之前,我得到了预期的结果,然后在执行第三个查询时,没有MAX(timestamp)作为MAX,我得到了预期的结果。当我添加它时,我只会在每个消息字符串应该是最后一个消息时获得第一个消息,而不管我使用的是最小还是最大,并且当显示2行时,行计数表示返回1行。有人知道我哪里出错了吗

    $sql="SELECT reply_chunk_id 
            FROM messages 
            GROUP BY reply_chunk_id 
            HAVING count(reply_chunk_id) > 1 ";
    $stmt16 = $conn->prepare($sql);
    $result=$stmt16->execute(array('specified_user'));
    while($row = $stmt16->fetch(PDO::FETCH_ASSOC)){
        $sql="SELECT user,reply_chunk_id, MIN(timestamp) AS grp_timestamp
                FROM messages WHERE reply_chunk_id=?
                GROUP BY reply_chunk_id HAVING user=?";
        $stmt17 = $conn->prepare($sql);
        $result=$stmt17->execute(array($row['reply_chunk_id'],'specified_user'));
        while($row2 = $stmt17->fetch(PDO::FETCH_ASSOC)){
            $sql="SELECT message, MAX(timestamp) as max FROM messages WHERE reply_chunk_id=?";
            $stmt18 = $conn->prepare($sql);
            $result=$stmt18->execute(array($row2['reply_chunk_id']));
            while($row3 = $stmt18->fetch(PDO::FETCH_ASSOC)){
                echo '<p>'.$row3['message'];
            }
        }
    }
    echo ' '.$stmt18->rowCount();
    

    由于
    消息
    未分组,因此您将从组中获得确切的
    消息
    。如果您想要带有时间戳的
    消息
    ,则需要显式选择它:

    SELECT message, timestamp AS max
        FROM messages 
        WHERE reply_chunk_id=:rcid
          AND timestamp=(SELECT MAX(timestamp) 
                             FROM messages 
                             WHERE reply_chunk_id=:rcid)
    
    或:

    第二个查询通过选择具有最高
    id
    的消息来打破联系(在不太可能但可能有多人同时发布的情况下)

    一般反馈 在循环中设置的许多变量是不变的,因此应该移到循环之外

    $stmt17将最多返回一个结果。此外,$stmt18将始终只返回一个结果。将第二个内部
    while
    循环(对于$stmt17)重写为
    if
    语句,并简单地从
    $stmt18
    中获取结果,就目的而言,这是等效的、更清晰的

    try {
      $threadSql="SELECT reply_chunk_id 
              FROM messages 
              GROUP BY reply_chunk_id 
              HAVING count(reply_chunk_id) > 1 ";
      $firstUserSql="SELECT user, MIN(timestamp) AS grp_timestamp
              FROM messages WHERE reply_chunk_id=?
              GROUP BY reply_chunk_id HAVING user=?";
      $lastMsgSql="SELECT message, MAX(timestamp) as max FROM messages WHERE reply_chunk_id=?";
      $threadQuery = $conn->prepare($threadSql);
      $threadQuery->setFetchMode(PDO::FETCH_ASSOC);
      $firstUserQuery = $conn->prepare($firstUserSql);
      $lastMsgQuery = $conn->prepare($lastMsgSql);
    
      $result=$threadQuery->execute(array('specified_user'));
      foreach ($threadQuery AS $thread){
          $result=$firstUserQuery->execute(array($thread['reply_chunk_id'],'specified_user'));
          if (FALSE !== ($firstUser = $firstUserQuery->fetch(PDO::FETCH_ASSOC))) {
              $result=$lastMsgQuery->execute(array($thread['reply_chunk_id']));
              $lastMsg = $lastMsgQuery->fetch(PDO::FETCH_ASSOC);
              echo '<p>'.$lastMsg['message'].'</p>';
          }
      }
      echo ' ' . $lastMsgQuery->rowCount();
    } catch (PDOException $exc) {
      ...
    }
    

    这将选择指定用户启动的所有具有响应的线程,以及最近的响应。

    您的消息是否具有唯一id?(提示:发布您的
    CREATE TABLE
    语句)。是的,它们有一个名为id的字段,该字段是自动递增的,reply\u chunk\u id但是可以与其他消息相同,因为相同的回复id表示相关的回复消息,我将发布表创建如果您对中间结果感兴趣,或者“选择”是一个可行的答案吗?我对intermediate不感兴趣,只是用户启动的线程的最大时间戳的结果,这是一个称为“最新回复”的排序视图,其中每个线程的最新回复基本上显示为快照。我非常感谢您的帮助,你在帮助我发展技能和回答我的问题方面做得非常出色。我只是有一些简短的问题。1.像您建议的那样的sql查询不会占用很多资源吗?2.我不完全确定你的第一个建议是怎么回事,因为我对php编程还是有点陌生,而且使用了相当简单的技术。我不理解的部分是if(虚线,我以前从未见过。3.我注意到您使用了try-and-catch。我应该在每个查询中使用它吗?再次感谢您的帮助。1.这取决于有多少个结果。使用多个查询也会对服务器资源产生负面影响,并且可能需要更长的时间。一般来说,最好不要使用数据库处理需要组合与给定属性匹配的数据的任务(将SQL语句视为声明属性;DBMS返回具有这些属性的数据)。这就剩下了更改任务(例如显示数据)对于编程语言。2.这一行可以很容易地分成两行:赋值和与FALSE的比较。当没有更多行时,从DB查询中获取结果通常返回FALSE;mysql、mysqli和PDO驱动程序都会这样做。如果查询将返回0或1行,则
    If
    可以通过检查获取的v值为FALSE。
    !==
    类似于
    !=
    ,但不处理类型;
    FALSE==0
    ,但
    FALSE!==0
    。3.您应该始终处理错误。try/catch假设您已将错误模式设置为
    PDO::ERRMODE\u异常
    ,在这种情况下,try/catch是必需的。有时设置t更合理他将错误模式转换为其他模式,并检查返回成功或失败的方法的返回值(例如PDOStatement::execute),但将一系列PDO方法调用封装在一个try/catch中通常更容易理解,因为调用通常需要按顺序成功完成。更大、更复杂的变化是分离访问数据库的代码(也称为数据访问层)来自表示数据的代码。这些是不同的,分离它们可以让您轻松地更改其中一个而不影响另一个,并提供相同数据的不同表示。应用是实现这种分离的一种方法。
    SELECT message, timestamp AS max
        FROM messages 
        WHERE reply_chunk_id=?
        ORDER BY timestamp DESC, id
        LIMIT 1
    
    try {
      $threadSql="SELECT reply_chunk_id 
              FROM messages 
              GROUP BY reply_chunk_id 
              HAVING count(reply_chunk_id) > 1 ";
      $firstUserSql="SELECT user, MIN(timestamp) AS grp_timestamp
              FROM messages WHERE reply_chunk_id=?
              GROUP BY reply_chunk_id HAVING user=?";
      $lastMsgSql="SELECT message, MAX(timestamp) as max FROM messages WHERE reply_chunk_id=?";
      $threadQuery = $conn->prepare($threadSql);
      $threadQuery->setFetchMode(PDO::FETCH_ASSOC);
      $firstUserQuery = $conn->prepare($firstUserSql);
      $lastMsgQuery = $conn->prepare($lastMsgSql);
    
      $result=$threadQuery->execute(array('specified_user'));
      foreach ($threadQuery AS $thread){
          $result=$firstUserQuery->execute(array($thread['reply_chunk_id'],'specified_user'));
          if (FALSE !== ($firstUser = $firstUserQuery->fetch(PDO::FETCH_ASSOC))) {
              $result=$lastMsgQuery->execute(array($thread['reply_chunk_id']));
              $lastMsg = $lastMsgQuery->fetch(PDO::FETCH_ASSOC);
              echo '<p>'.$lastMsg['message'].'</p>';
          }
      }
      echo ' ' . $lastMsgQuery->rowCount();
    } catch (PDOException $exc) {
      ...
    }
    
    SELECT mchunk.reply_chunk_id, 
           muser.user, MIN(muser.`timestamp`) AS grp_timestamp, 
           mmax.message, mmax.`timestamp` AS max
      FROM messages AS mchunk
      JOIN messages AS muser
        ON mchunk.reply_chunk_id = muser.reply_chunk_id
      JOIN messages AS mmax
        ON mchunk.reply_chunk_id = mmax.reply_chunk_id
      WHERE mmax.timestamp=(SELECT MAX(timestamp) FROM messages AS m WHERE m.reply_chunk_id=mchunk.reply_chunk_id)
      GROUP BY mchunk.reply_chunk_id, muser.user
      HAVING count(mchunk.reply_chunk_id) > 1
        AND muser.user IN ('steve', '0010')
    ;