繁体   English   中英

从一个表中获取不在另一个表中的所有数据 MySQL

[英]Get all data from one table that's not in another table MySQL

我有一个消息表:

  mysql> describe messages;
+-----------+--------------+------+-----+-------------------+-----------------------------+
| Field     | Type         | Null | Key | Default           | Extra                       |
+-----------+--------------+------+-----+-------------------+-----------------------------+
| id        | int(11)      | NO   | PRI | NULL              | auto_increment              |
| user1_id  | int(11)      | NO   |     | NULL              |                             |
| user1     | varchar(255) | NO   |     | NULL              |                             |
| user2_id  | int(11)      | NO   |     | NULL              |                             |
| user2     | varchar(255) | NO   |     | NULL              |                             |
| message   | text         | YES  |     | NULL              |                             |
| timestamp | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| user1read | varchar(3)   | NO   |     | NULL              |                             |
| user2read | varchar(3)   | NO   |     | NULL              |                             |
+-----------+--------------+------+-----+-------------------+-----------------------------+
9 rows in set (0.00 sec)

然后我有一个阻塞的表:

 mysql> describe blocked;
+-----------------+---------+------+-----+---------+-------+
| Field           | Type    | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+-------+
| user_id         | int(11) | NO   | PRI | NULL    |       |
| blocked_user_id | int(11) | NO   | PRI | NULL    |       |
+-----------------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

我想要做的是让所有数据显示在页面上的单独 div 中。 该脚本每秒被调用一次。 无论阻止状态如何,我最终得到的查询都会产生所有消息。

所以,假设我的 ID 是 1,一个被阻止的用户的 ID 是 5,用户 5 不应该出现在列表中。 如果其他用户登录,也会发生同样的情况。

在弄乱了该查询一段时间后,我尝试了第二个查询。 更糟糕的是,尽管使用相同查询通过手动 SQL 条目返回数据,但页面上没有任何内容出现。

该文件相当小,所以我将发布整个内容:

编辑:第一个查询实际上是显示所有消息,包括我自己作为消息,这显然是错误的。 看来我的查询比我想象的更糟糕。

 <?php
session_start();

include '../../../config/DB.php';

$username = $_SESSION['logged_in']; //to use in queries

try {
    $db = new DB(); //new DB object
} catch (Exception $e) {
    $e->getMessage();
}

try {
    $names = array(); //to store during foreach iterations

    //get the id for the other query attempt
    $id_result = $db->getRow('SELECT id FROM users WHERE username=?', [$username]);
    $id = $id_result['id'];

    foreach ($messages_result = $db->getRows('SELECT messages.user1, messages.user2, messages.timestamp, messages.message, messages.user2read, users.avatar
                                                    FROM messages
                                                    LEFT JOIN users ON messages.user1 = users.username
                                                    WHERE messages.user2 = ? AND 
                                                    (users.id NOT IN (SELECT user_id FROM blocked))
                                                    OR (users.id NOT IN (SELECT blocked_user_id FROM blocked))
                                                    ORDER BY timestamp DESC', [$username]) as $result) {
        $sender = $result['user1'];
        $time = $result['timestamp'];
        $message = $result['message'];
        $avatar = $result['avatar'];
        $user2read = $result['user2read'];

        //Do this so users will only show once.
        //One div per user, and when clicked
        //all messages are shown elsewhere on a page.
        if (!in_array($sender, $names)) {
            $names[] = $sender;

            //If the message is unread, show name in bold
            //Else show regular text
            //$avatar has been removed from the html for now
            //It shows up in an <img> tag
            if ($user2read === 'no') {
                echo '<div id="single_message" data-sender="' . $sender . '"><p style="padding-left:8px;"><p><a class="link" style="font-weight:bold;font-size:16px;" href=' . $sender . '>' . $sender . '</a></strong></p><p style="white-space:pre-wrap;margin-left:8px;margin-right:8px;">' . $message . '</p><p style="padding-left:8px;border-bottom: 1px solid #ccc;">' . $time . '</p></div>';
            } else {
                echo '<div id="single_message" data-sender="' . $sender . '"><p style="padding-left:8px;"><p><a class="link" href=' . $sender . '>' . $sender . '</a></p><p style="white-space:pre-wrap;margin-left:8px;margin-right:8px;">' . $message . '</p><p style="padding-left:8px;border-bottom: 1px solid #ccc;">' . $time . '</p></div>';
            }

        } else {
            continue;
        }
    }

} catch (Exception $e) {
}

这是我尝试的第二个查询(我将只显示 foreach)。 这是页面上不显示任何内容的页面。

 foreach($messages_result = $db->getRows('SELECT * FROM messages m LEFT JOIN blocked b ON ((m.user1_id = b.user_id OR m.user2_id = b.user_id)
                                                    AND (m.user1_id = b.blocked_user_id OR m.user2_id = b.blocked_user_id))
                                                    WHERE (m.user1_id = 1 OR m.user2_id = 1) HAVING m.user_id IS NULL
                                                    ORDER BY timestamp DESC', [$id]) as $result) {

我在这里错过了什么吗?

WHERE (m.user1_id = 1 OR m.user2_id = 1) HAVING m.user_id IS NULL我认为它相互矛盾 bcos 你有这个加入ON ((m.user1_id = b.user_id OR m.user2_id = b.user_id) AND (m.user1_id = b.blocked_user_id OR m.user2_id = b.blocked_user_id)) ....就像取消对方一样......

纠正这个......也许可以......祝你好运

阿左上阻止用户加入与匹配user2 (“我”),以blocked.user_id ,谁块,而人user1blocked.blocked_user_id用户谁被阻塞,如果结果是NULL(又名b.user_id IS NULL) ,那么就没有块了。

foreach($messages_result = $db->getRows('
SELECT messages.user1, messages.user2, messages.timestamp, messages.message, messages.user2read, users.avatar
FROM messages
LEFT JOIN users ON messages.user1 = users.username
LEFT JOIN blocked b ON b.user_id = messages.user2_id AND b.blocked_user_id = messages.user1_id
WHERE messages.user2 = ? AND b.user_id IS NULL
ORDER BY timestamp DESC',[$username]) as $result) {
...

我有一个类似的脚本,它从没有被阻止的用户表中获取所有用户,而不是从消息表中获取数据。 由于这仅将用户 id 与被阻止的 id 进行了比较,因此我可以使用一个查询块进行比较。 但是,我需要检查消息中 user1_id 和 user2_id 之间的所有可能性,以及阻止中的 user_id 和 blocks_user_id 之间的所有可能性。 这需要一个额外的块,它是第一个块的反向版本。

我将通过显示用户的 id 和用户名,然后是被阻止表中的每个人,然后是使用被阻止表中的 id 的结果来展示这是如何成功的。

mysql> select id, username from users;
+----+-----------------+
| id | username        |
+----+-----------------+
|  1 | csheridan       |
|  2 | testuser        |
|  3 | testuser2       |
|  4 | washington_user |
+----+-----------------+
4 rows in set (0.00 sec)

mysql> select * from blocked;
+---------+-----------------+
| user_id | blocked_user_id |
+---------+-----------------+
|       1 |               2 |
|       1 |               4 |
+---------+-----------------+
2 rows in set (0.00 sec)

mysql> SELECT m.* FROM messages m   
       WHERE NOT EXISTS (SELECT 1 FROM blocked b 
       WHERE b.user_id = m.user1_id AND b.blocked_user_id = 1) 
       AND NOT EXISTS 
       (SELECT 1 FROM blocked b WHERE b.blocked_user_id = m.user1_id AND b.user_id = 1)   
       AND NOT EXISTS (SELECT 1 FROM blocked b WHERE b.user_id = m.user2_id AND b.blocked_user_id = 1) 
       AND NOT EXISTS (SELECT 1 FROM blocked b WHERE b.blocked_user_id = m.user2_id AND b.user_id = 1) 
       ORDER BY timestamp DESC;
+----+----------+-----------+----------+-----------+----------------+---------------------+-----------+-----------+
| id | user1_id | user1     | user2_id | user2     | message        | timestamp           | user1read | user2read |
+----+----------+-----------+----------+-----------+----------------+---------------------+-----------+-----------+
|  2 |        3 | testuser2 |        1 | csheridan | Hey!           | 2018-11-14 12:12:35 | yes       | no        |
|  4 |        3 | testuser2 |        1 | csheridan | Are you there? | 2018-11-14 12:12:35 | yes       | no        |
+----+----------+-----------+----------+-----------+----------------+---------------------+-----------+-----------+
2 rows in set (0.00 sec)

mysql> SELECT m.* FROM messages m   
       WHERE NOT EXISTS (SELECT 1 FROM blocked b  
       WHERE b.user_id = m.user1_id AND b.blocked_user_id = 2) 
       AND NOT EXISTS (SELECT 1 FROM blocked b WHERE b.blocked_user_id = m.user1_id AND b.user_id = 2)   
       AND NOT EXISTS (SELECT 1 FROM blocked b WHERE b.user_id = m.user2_id AND b.blocked_user_id = 2) 
       AND NOT EXISTS (SELECT 1 FROM blocked b WHERE b.blocked_user_id = m.user2_id AND b.user_id = 2) 
       ORDER BY timestamp DESC;
+----+----------+-----------------+----------+----------+---------------------+---------------------+-----------+-----------+
| id | user1_id | user1           | user2_id | user2    | message             | timestamp           | user1read | user2read |
+----+----------+-----------------+----------+----------+---------------------+---------------------+-----------+-----------+
|  7 |        4 | washington_user |        2 | testuser | Hey man! What's up? | 2018-11-14 14:32:27 | yes       | no        |
|  8 |        4 | washington_user |        2 | testuser | Hello there.        | 2018-11-14 14:32:27 | yes       | no        |
+----+----------+-----------------+----------+----------+---------------------+---------------------+-----------+-----------+
2 rows in set (0.00 sec)

所以,问题是我在正确的轨道上,我只需要另一个街区。 首先,我检查了blocked.user_id = messages.user1_id ANDblocked.user_id = ?,然后我检查了user2_id 的其他条件。 除非有人提出更紧凑的查询,否则这就是我所需要的。 如果我只做了第一个块,它不会检查所有条件并且仍然返回被阻止的用户,因为它没有从消息中检查 user1_id 和 user2_id。

暂无
暂无

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

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