Mysql查询让我感到困惑

3

新文章 我最终避免使用那个查询。我无法得到我想要的结果。为了获得所需的结果,我想出了这个...

此外,如果你们能想出那个查询,我真的希望能够去掉这个解决方法。

非常感谢迄今为止所有的帮助!

function get_converstations($data)
{  
    //get possible senders into an array
    $sender_sql = "SELECT DISTINCT `users`.`aid` AS `aid`, `users`.`nickname` AS `nickname`
                FROM `users`,`messages` 
                WHERE  `messages`.`sender` =  '".$data['aid']."'
                AND `messages`.`recipient` = `users`.`aid`";
    $query = mysql_query($sender_sql);
    if(mysql_num_rows($query) > 0)
    {   
        $sender_data = array();
        while ($row = mysql_fetch_array($query)){
                $sender_data[$row['aid']] = $row['nickname'];
        }
    }           


    //get possible recipients into an array         
    $recipient_sql = "SELECT DISTINCT `users`.`aid`, `users`.`nickname` 
                FROM `users`,`messages` 
                WHERE  `messages`.`recipient` =  '".$data['aid']."'
                AND `messages`.`sender` = `users`.`aid`";                   
    $query = mysql_query($recipient_sql);
    if(mysql_num_rows($query) > 0)
    {
        while ($row = mysql_fetch_array($query)){
                $recipient_data[$row['aid']] = $row['nickname'];
        }
    }       

    //merge the arrays to overrite any duplicate people.
    $no_keys_persons = array_merge($sender_data, $recipient_data);

    //create a new array with keys
    foreach($no_keys_persons as $aid => $nickname)
    {
        $persons[] = array(
            "aid" => $aid,
            "nickname" => $nickname
        );
    }

    //print_r($persons);
    //create the conversations array
    foreach($persons as $person)
    {
        $sql = "SELECT * FROM `messages` WHERE `sender` = '".$data['aid']."' AND `recipient` = '".$person['aid']."' OR `sender` = '".$person['aid']."' AND `recipient` = '".$data['aid']."' ORDER BY `id` DESC LIMIT 1";
        $query = mysql_query($sql);
        if(mysql_num_rows($query) > 0)
        {
            while($row = mysql_fetch_array($query))
            {
                $conversations[] = array(
                    "person_aid" => $person['aid'],
                    "person_nickname" => $person['nickname'],
                    "sender" => $row['sender'],
                    "recipient" => $row['recipient'],
                    "body" => $row['body'],
                    "timestamp" => $row['timestamp'],
                    "ip" => $row['ip']
                );
            }
        }

    }

    //print_r($conversations);                              
    return $conversations;

}

然后当我在我的控制器上调用该函数时...
//create the data array from url
$data = array(
    "aid" => $_GET['aid'],
    "nickname" => $_GET['nickname'],
    "ip" => $_SERVER['REMOTE_HOST'],
);

//instantiate any classes
include 'db.php';
include 'messages_model.php';
$messages = new messages_model();

$coversations = $messages->get_converstations($data);

foreach ($coversations as $conversation)
{
    echo '&conversation=';
    echo '&sender='.$conversation['sender'];
    if($conversation['sender'] === $data['aid']) { echo '&sender_nickname='.$data['nickname']; } else { echo '&sender_nickname='.$conversation['person_nickname']; }
    echo '&recipient='.$conversation['recipient'];
    if($conversation['recipient'] === $data['aid']) { echo '&recipient_nickname='.$data['nickname']; } else { echo '&recipient_nickname='.$conversation['person_nickname']; }
    echo '&body='.$conversation['body'];
    echo '&timestamp='.$conversation['timestamp'];

}

原始信息 我很困惑。请看看能否帮我组合这个查询。

我有一张名为messages的表。

    CREATE TABLE  `db.app`.`messages` (
    `id` INT( 32 ) NOT NULL AUTO_INCREMENT ,
    `sender` VARCHAR( 64 ) NOT NULL ,
    `recipient` VARCHAR( 64 ) NOT NULL ,
    `body` TEXT NOT NULL ,
    `timestamp` INT( 32 ) NOT NULL ,
    PRIMARY KEY (  `id` )
    ) ENGINE = MYISAM ;

还有一个名为“users”的表。

    CREATE TABLE  `db.app`.`users` (
    `id` INT( 32 ) NOT NULL AUTO_INCREMENT ,
    `nickname` VARCHAR( 64 ) NOT NULL ,
    PRIMARY KEY (  `id` )
    ) ENGINE = MYISAM ;

当一条消息被创建时,它会将发送者的ID插入到messages.sender中,将接收者的ID插入到messages.recipient中,并插入消息正文和UNIX时间戳。这部分已经正常运作。
我的问题在于如何获取所有唯一对话的列表(就像iPhone上的短信一样)。
因此,如果我们有以下数据...
messages table;   
 id  | sender | recipient | body | timestamp  
 1   | 1234 | 5678 | testing message | 1290233086  
 2   | 5678 | 1234 | testing reply | 1290233089  

users table;  
 id | nickname   
 1234 | john  
 5678 | peter  

我希望能够生成以下格式的查询结果...
results;  
 other_person_id | other_person_nickname | last_message  | last_message_timestamp  
 1234            | john                  | testing reply | 1290233089  

我真的无法理解这个查询语句...


添加一张名为“会话(conversations)”的新表,然后;-) - zerkms
我在思考,那真的是唯一的解决方案吗? - Peter
没有任何东西能告诉我们一条消息是否属于特定的对话。如果John和Peter有一次对话,一个月后他们又开始了全新的对话,那该怎么办呢? - Vincent Savard
我的视图设置为显示所有线程,而不仅仅是特定的对话。因此,在约翰的视图中,两个对话都应该显示为“Peter”。 - Peter
3个回答

0

这正是你想要的:

SELECT users.id AS other_person_id, users.nickname AS other_person_nickname, messages.body AS last_message, messages.timestamp AS last_message_timestamp FROM messages LEFT JOIN users ON (messages.recipient = users.id) ORDER BY messages.id DESC LIMIT 1

0

这是一个使用JOIN的任务,大概长这样:

SELECT users.id, users.nickname, messages.body, messages.timestamp 
   FROM messages JOIN users ON messages.recipient = users.id

此外,您应该重新构建表格,以便将ID存储为正确的数据类型,因为这样做会使其更加清晰,并且可以避免数据库在稍后强制转换或抛出错误。
CREATE TABLE  `db.app`.`messages` (
  `id` INT( 32 ) NOT NULL AUTO_INCREMENT ,
  `sender` INT( 32 ) NOT NULL ,
  `recipient` INT( 32 ) NOT NULL ,
  `body` TEXT NOT NULL ,
  `timestamp` INT( 32 ) NOT NULL ,
  PRIMARY KEY (  `id` )
) ENGINE = MYISAM ;

彼得:一如既往,这取决于具体情况。利亚姆指出的是,您的用户表使用INT(32)类型,而消息表中的外键引用(发送者和接收者)使用varchar(64)。每次比较ID时,MySQL都必须将int转换为varchar,这会减慢速度。对于ID,我总是使用无符号INT(或tinyint / smallint,如果我希望表保持非常小)。 - kander

0

类似这样的代码应该可以实现(发送者 ID 假设为 1,接收者 ID 假设为 2):

SELECT users.id, users.nickname, messages.body, messages.timestamp
FROM messages
JOIN users ON messages.recipient = users.id
          AND messages.sender    = 1
          AND messages.recipient = 2

这让我更接近目标了,但我需要进一步完善结果。我想要的结果只显示两个用户之间的一条消息。非常感谢你,你让我离完成这个目标又近了一步! - Peter
你觉得在这里加上 "AND messages.timestamp = (select max(messages.timestamp) from messages)" 行不行呢?假设你想要最新的消息。 - crnlx
那部分已经处理了,但如果用户收到了消息却没有回复,我仍然会遇到问题。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接