【问题标题】:Join query not working the way I want加入查询没有按我想要的方式工作
【发布时间】:2015-06-23 20:58:24
【问题描述】:

我尝试将两个 MySQLi 查询转换为一个连接查询。它在某种程度上有效,但并没有按照我想要的方式运作。

我有 2 张桌子、票和回复。我正在从票证查询中选择信息,并且我正在从其中存储有票证 ID 的回复表中选择信息。到目前为止,我正在输出初始票证消息和第一个回复,但是对于该票证的每个回复,它都会重复此操作。所以我目前的输出是这样的:

Initial message
First reply
Initial message
Second reply
Initial message
Third reply

它为这张票的每个回复输出初始消息。我只希望它输出一次初始消息,然后输出这张票的回复。到目前为止,我已经尝试了几种不同的方法来执行此连接查询,但这就是我现在所拥有的:

 $ticket = $db->conn->query("SELECT tickets.client, tickets.subject, tickets.message, tickets.created_at, tickets.status,
                                                   replies.reply_username, replies.reply_message, replies.reply_time
                                            FROM tickets, replies
                                            WHERE tickets.id = replies.ticket_id") or die(mysqli_error($db->conn));

我做错了吗?我的逻辑有问题吗?

我还想补充一点,我之前的查询有“INNER join”和“left join”,但内部给我的输出与我目前的输出相同。

有点乱,但这是查询后运行的代码。

while($rows = $ticket->fetch_object()) {
    if($_SESSION['ticket_username'] == $rows->client) {
        $status = $rows->status;
        echo '
            <h3>'.$rows->subject.'</h3>
            <small>Created by '.$rows->client.', '.$timeAgo->inWords($rows->created_at).'</small>
            <hr>
            <p>'.nl2br($rows->message).'</p>
            <hr>
            <small>Reply from '.$rows->reply_username.', '.$timeAgo->inWords($rows->reply_time).'</small>
            <p>'.nl2br($rows->reply_message).'</p>
            <hr>
        ';

    } else {
        header("Location: index");
    }

    if(!empty($errors) && is_array($errors)) {
        foreach($errors as $error) {
            echo $error;
        }
    }
}

【问题讨论】:

  • 查询后粘贴整个代码
  • 正如@PlatinumIndustries 所说,之后我们将需要代码;您的查询将为您提供所有正确的信息。您的问题似乎在于您如何处理它。
  • 对不起,我添加了查询后运行的代码

标签: php join mysqli


【解决方案1】:

您没有做太多事情,但您的查询似乎没问题(基于逻辑),只留下一个可能的罪魁祸首。

默认情况下,PDO 使用PDO::FETCH_BOTH 作为其获取结果。这意味着它将每列映射到其名称和“整数”列名称。

您可能需要在查询中使用$statement-&gt;fetchAll(PDO::FETCH_ASSOC); 以获得您期望的输出。

在此处阅读有关PDOStatement::fetchAll 的更多信息。

【讨论】:

    【解决方案2】:

    这可能需要一些调整,但这是我的处理方式:

    while($rows = $ticket->fetch_object()) {
        if($_SESSION['ticket_username'] == $rows->client) {
            $status = $rows->status;
            if($lastID != $rows->id){
                echo '
                    <h3>'.$rows->subject.'</h3>
                    <small>Created by '.$rows->client.', '.$timeAgo->inWords($rows->created_at).'</small>
                    <hr>
                    <p>'.nl2br($rows->message).'</p>
                    <hr>';
            }
            $lastID = $rows->id;
    
            echo '
                <small>Reply from '.$rows->reply_username.', '.$timeAgo->inWords($rows->reply_time).'</small>
                <p>'.nl2br($rows->reply_message).'</p>
                <hr>';
    
        } else {
            header("Location: index");
        }
    
        if(!empty($errors) && is_array($errors)) {
            foreach($errors as $error) {
                echo $error;
            }
        }
    }
    

    这样做是检查当前打印的票证 ID 是否与上次打印的票证 ID 相同;如果是,请不要再次打印初始消息。我不确定您的查询是如何对结果进行排序的,因此您可能需要在其中添加一个 ORDER BY ticket.id, replies.ticket_id 以确保它们都被组合在一起。

    【讨论】:

    • 感谢您的回复。我确实使用并调整了您的答案,但得到了相同的结果。我现在已经制定了一种解决方法来实现我的结果。与您的类似,我只是创建一个计数变量并在开始循环数据库结果时向其添加一个,然后使用简单的检查来查看计数是否等于 1 并输出初始消息。
    • 糟糕。可能是因为lastID 变量是如何在while() 循环中首次声明的。我对 PHP 不太熟悉,但通常在循环中定义一个变量会导致它每次都被声明,从而重置它的内容,并且不允许 if 检查以它应该的方式运行!
    猜你喜欢
    • 2021-12-15
    • 2011-04-18
    • 2023-03-15
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    相关资源
    最近更新 更多