繁体   English   中英

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

[英]SQL MAX() in multiple query string

我有3个查询字符串,旨在

  1. 查找哪些消息还有其他具有相同ID(代表回复)的消息
  2. 在输入该消息字符串的第一条消息(最小时间戳)时,查找第一个查询结果中的哪些消息具有指定的用户
  3. 查找该消息字符串中的最新消息(最大时间戳)

问题来自第三个查询。 我得到了直到第二个查询的预期结果,然后执行第三个查询时,没有将MAX(timestamp)设置为max,我得到了预期的结果。 当我添加它时,无论是使用min还是max,我只会获得每个消息字符串中的第一条消息,而不管我是使用min还是max,并且当显示两行时,行数会返回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();

根据要求创建消息的表视图:

CREATE TABLE IF NOT EXISTS `messages` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `timestamp` int(11) NOT NULL,
  `user` varchar(25) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 'anonimous',
  `message` varchar(2000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `topic_id` varchar(35) NOT NULL,
  `reply_chunk_id` varchar(35) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

由于未对message进行分组, 因此未定义您将从该组中获得的确切message 如果您想要带有最大时间戳的message ,则需要明确选择它:

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

要么:

SELECT message, timestamp AS max
    FROM messages 
    WHERE reply_chunk_id=?
    ORDER BY timestamp DESC, id
    LIMIT 1

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

一般意见

您在循环中设置的许多变量都是不变的,因此应将其移出循环。

$ stmt17将最多返回1个结果。 而且,$ 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) {
  ...
}

最后,一个SQL语句可以替换许多PHP代码:

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')
;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM