Получить все данные из одной таблицы, которой нет в другой таблице 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)

Я пытаюсь сделать так, чтобы все данные отображались в отдельных элементах на странице. Этот скрипт вызывается каждую секунду. В результате запроса, который я закончил, были получены все сообщения, независимо от статуса блокировки.

Итак, допустим, мой идентификатор равен 1, а заблокированный идентификатор пользователя равен 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) {

Я что-то здесь упускаю?

-1

Решение

WHERE (m.user1_id = 1 OR m.user2_id = 1) HAVING m.user_id IS NULL я думаю, что это противоречит друг другу, потому что у вас есть это присоединиться 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))…. это как отменить друг друга ……..

Исправьте это …. возможно может …. удачи

0

Другие решения

Левое присоединение к заблокированным пользователям с соответствием user2 («я тоже blocked.user_id, человек, который блокирует, и user1 против blocked.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) {
...
0

У меня есть похожий сценарий, который получает всех пользователей из таблицы пользователей, которые не заблокированы, в отличие от получения данных из таблицы сообщений. Поскольку это сравнивало только идентификатор пользователя с заблокированными идентификаторами, я смог сделать это с помощью одного блока запроса. Однако мне нужно было проверить все возможности между user1_id и user2_id из сообщений, а также user_id и block_user_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)

Итак, проблема была в том, что я был на правильном пути, мне просто нужен был еще один блок. Сначала я проверил заблокированный.user_id = messages.user1_id И заблокированный.user_id =?, Затем я проверил Другой условие для user2_id. Если кто-то не придет с более компактным запросом, это то, что мне нужно.
Если бы я только сделал первый блок, он не проверил все условия и все еще возвратил заблокированных пользователей, так как он не проверял и user1_id, и user2_id из сообщений.

0
По вопросам рекламы [email protected]