Запрос к БД MySQL

Funch

Здраствуйте. Делаю чат. Проектирую таблицу с сообщениями. В комнате выводится сообщения из БД.
поля в таблице:
id сообщения,
id комнаты,
дата и время,

id пользователя который отправил сообщение,
id пользователя кому отправлено сообщение,
private —
приватность сообщения (0 — видят все, 1 видит только тот пользователь, которому отправлено которому отправлено сообщение и тому пользователю, который отправил)

Запрос примерно таков:
ВЫБРАТЬ все поля
ИЗ
таблицы message
ГДЕ
с пометкой ‘1’ в private поле не является id тому пользователю, которому отправлено данное сообщение
И
с пометкой ‘1’ в private поле не является id того пользователя, который отправил данное сообщение
СОРТИРОВКА ПО id сообщения
С ЛИМИТОМ 200
сообщений

ЛИМИТ нужен для того, чтобы для каждого пользователя выборка из БД была 200 сообщений не зависимо приватное сообщение или нет. Это для постраничной навигации: 10 страниц по 20 сообщений на странице.

ВОПРОС!!! как сделать такой запрос?
ГДЕ с пометкой ‘1’ в private поля не является id тому пользователю, которому отправлено данное сообщение
И с пометкой ‘1’ в private поля не является id того пользователя, который отправил данное сообщение

ПРИМЕЧАНИЕ:
Можно было бы выбрать все сообщения в количестве 200 штук, не зависимо от является ли отправитель автор приватного сообщения и является ли получатель приватного сообщения, и уже при выводе сообщений проверять является ли данное приватное сообщение того пользователя, который отправил или тому пользователю, которому отправлено, если да, то выводить это сообщение,
if($private == 1 && $id_отп-ля == $id_поль-ля || $id_получ-ля == $id_поль-ля)
выводим сообщение
else continie;
но тут есть проблема:
Допустим будет 5 приватных сообщений.
Из БД выводится 200 сообщений независимо от приватности и, если такой метод отображения использовать, то другие пользователи увидят на 5 сообщений, а именно 195.
Следовательно, на первой странице они увидят не 20 сообщений, а на 5 меньше, то есть 15.

 

Drunkenmunky

Код (Text):
  1. …WHERE `id_user` NOT IN(123,234) AND `privat`  !=1
 

Funch

Код (Text):
  1. WHERE `id_user` NOT IN(123,234) AND `privat`  !=1

Где 123,234 — это поля id пользователя который отправил сообщение и id пользователя кому отправлено сообщение?

 

Drunkenmunky

WHERE `id_user_in` NOT IN(123,234) AND `id_user_out` !=345 AND `privat` !=1

 

miketomlin

@Funch, нужно проектировать таблицы в соответствии с выполняемыми запросами, а не усложнять запросы из-за неподходящим образом спроектированных таблиц. Например, ЛС можно отображать в приватных чатах, а в сообщениях вместо флага приватности хранить идентификатор (приватного) чата (значение 0, например, указывает на публичный чат).

 

Funch

В том то и смыл чтобы отображать приватные сообщения в общей комнате.

 

Funch

Пожалуйста, объясните данный запрос.

 

Drunkenmunky

Выбрать всё, кроме 123 и 234 в колонке in, при этом не равное 345 в колонке out, и при этом не равное 1 в колонке privat.
Это не решение конкретно вашей задачи.
А пример постановки условий.
Так как задача неконкретна и описана непродуманно.
Вместо AND можно использовать OR.

 

Funch

Опишите тогда постановку задачи со своей стороны, пожалуйста.

 

Drunkenmunky

Элементарно.
Живая таблица, или её часть со структурой. Какие строки вывести.

 

Funch

Код (Text):
  1. CREATE TABLE `test_table` (
  2.   `id` int UNSIGNED NOT NULL,
  3.   `id_who` int NOT NULL,
  4.   `id_to_whom` int NOT NULL,
  5.   `private` enum(‘0′,’1’) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT ‘0’,
  6.   `message` varchar(255) NOT NULL
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

это таблица

PHP:
  1. $mysqli = mysqli_connect(‘localhost’, ‘root’, ‘root’, ‘test’) or die(mysqli_error());
  2.  
  3. // * в качестве теста
  4. $id_user = 3;
  5. $sql = «SELECT *
  6.            FROM `test_table`
  7.                WHERE (`id_who` = ‘$id_user‘ AND private=»0″)
  8.                OR (`id_who` = ‘$id_user‘ AND private=»1″)
  9.                OR (`id_who` != ‘$id_user‘ AND private=»0″)
  10.                OR (`id_to_whom` = ‘$id_user‘ AND private=»1″)
  11.                LIMIT 5″;
  12. echo $sql;
  13.  
  14. $result = mysqli_query($mysqli, $sql);
  15.  
  16.  
  17. for($i = 0; mysqli_num_rows($result) > $i; $i++){
  18.     $row[] = mysqli_fetch_assoc($result);
  19. }
  20.  
  21. print_r ($row);

а вот запрос, который работает, все отрабатывает, но какой-то он громоздкий

 

Drunkenmunky

Не совсем. Нет данных.

>а вот запрос, который работает, все отрабатывает, но какой-то он громоздкий

Работает быстро?

 

Funch

PHP:
  1. $start = microtime();
  2. // * в качестве теста
  3. $id_user = 3;
  4. $sql = «SELECT *
  5.            FROM `test_table`
  6.                WHERE (`id_who` = ‘$id_user‘ AND private=»0″)
  7.                OR (`id_who` = ‘$id_user‘ AND private=»1″)
  8.                OR (`id_who` != ‘$id_user‘ AND private=»0″)
  9.                OR (`id_to_whom` = ‘$id_user‘ AND private=»1″)
  10.                LIMIT 5″;
  11. $total_time = microtime() $start;
  12. echo $total_time; // 9.0000000000368E-6

0.0000090000 — это самое большое значение .

вот данные , которые хранятся в таблицею они тестовые

123.jpg

 

Drunkenmunky

Ну, таблица-то пока небольшая.
Добавьте индексы. Из private уберите сравнение, и сойдет.

 

Funch

какие ключи? что посоветуете?

 

Drunkenmunky

Например, out/in составной сделайте.
Остальное как обычно.

 

Funch

а для чего? можно узнать поподробней или дайте ресурс, где с этим можно ознакомиться
и почему сравнение в поле private убрать?

PHP:
  1. $sql = «SELECT *
  2.            FROM `test_table`
  3.                WHERE  private=»0″
  4.                OR (`id_who` = ‘$id_user‘ AND private=»1″)
  5.                OR (`id_to_whom` = ‘$id_user‘ AND private=»1″)
  6.                LIMIT 5″

и вот несколько строк кода сократил в запросе!

 

miketomlin

AND private = ‘1’ спокойно выносится за скобки и опускается.

 

Drunkenmunky

Funch

PHP:
  1. $sql = «SELECT *
  2.            FROM `test_table`
  3.                WHERE private=»0″
  4.                OR (`id_who` = ‘$id_user‘ OR `id_to_whom` = ‘$id_user‘)
  5.                LIMIT 200″;

Тогда уж вообще так.

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *