SQL, чтобы найти пользователей, которые текущий пользователь не любил/не любил


У меня очень длинный запрос, которая на мой взгляд выглядит некрасиво рядом со всеми аккуратный код в моем проекте. Мне было интересно, если есть способ, чтобы оптимизировать его или сделать его короче, по крайней мере:

$query = <<<SQL
    SELECT * FROM users 
    WHERE NOT EXISTS (
        SELECT id
        FROM profile_likes 
        WHERE profile_id = users.id
        AND viewer_id = $my_user->id
    )
    AND NOT EXISTS (
        SELECT id
        FROM profile_dislikes
        WHERE profile_id = users.id
        AND viewer_id = $my_user->id
    )
    AND id != $my_user->id
SQL

Этот запрос является частью пользовательский фильтр, который имеет назначение фильтровать пользователей, только что вошедшего в систему пользователя ($my_user) не любил/не любил еще.



128
1
задан 11 февраля 2018 в 04:02 Источник Поделиться
Комментарии
2 ответа

Вам действительно нужно, чтобы сохранить симпатии и антипатии в разных таблицах?

Мне кажется, что это будет почти то же самое с разными значениями в одном поле. Так может быть profile_reactions стол вместо. Делать это позволит упростить модель данных с двумя таблицами и, вероятно, будет более масштабируемым в будущем, если/когда вы хотите, чтобы объявление несколько типов реакции.

SELECT * обычно следует избегать. Это делает его более трудным для читателей кода, чтобы понять, какие поля они должны работать в результирующем наборе (им пришлось бы смотреть на схему базы данных, чтобы понять это). Она может быть более интенсивной пропускной способностью, чем необходимо. Вам нужно только несколько полей из таблицы с большим количеством полей, зачем тянуть все лишние данные? Это может сделать код более хрупким. Может схемы базы данных потенциально может изменить внесения ошибок в код?

Считать ли реляционного хранилища (т. е. MySQL) для этого в долгосрочной перспективе. Поскольку вы собираетесь иметь дело с большинство записей в этих таблицах, это запрос, который действительно может быть проблематичным с течением времени, все медленнее и медленнее, по мере роста пользовательской базы. Это просто не хорошо. Основной вопрос, Является ли любит/не любит (реакции) не имеют никакого смысла вне контекста владея пользователей. Мое предположение заключается в том, что они не. А если нет, то почему эти данные должны быть нормализованы в своей собственной таблице?

Эта модель данных является тот, который на самом деле работает достаточно хорошо в NoSQL хранилище, где модель данных может выглядеть так:

// User
{
"id": 123,
"reactions_to_users": {
234: "like",
456: "dislike",
789: "like",
...
}
"reactions_from_users": {
234: "like",
456: "dislike",
111: "like",
},
...
}

Поэтому, предполагая, что вы уже бы этот объект пользователя, загруженных ранее в коде (как вы знаете). Когда вы идете, чтобы сделать ваш запрос в хранилище данных, чтобы получить ООН-нравятся или не нравятся пользователи, Вы бы просто нужно получить идентификаторы пользователей при reactions_to_users и сделать запрос на сохранение данных для всех пользователей, вне этого набора.

Я думаю, что ваш фактический код SQL в PHP выглядит хорошо. Я предпочитаю использовать heredoc-синтаксиса nowdoc или как вы делаете. Я тоже предпочитаю по SQL читать больше вертикально, чем горизонтально, распадаясь на каждого SQL фразы, как вы сделали. Я бы не менял здесь свой стиль.

2
ответ дан 11 февраля 2018 в 05:02 Источник Поделиться

Лично я бы просто придерживаться того, что у вас уже есть.

Вы могли бы попробовать что-то вроде этого, хотя мне тоже это не выглядит опрятнее.
Вам понадобится профиль на базе данных, чтобы увидеть, если он выполняет лучше.

SELECT * 
FROM users
left outer join profile_likes on profile_likes.profile_id = users.id AND profile_likes.viewer_id = $my_user->id
left outer join profile_dislikes on profile_dislikes.profile_id = users.id AND profile_dislikes.viewer_id = $my_user->id
where users.id <> $my_user->id
having profile_likes.profile_id is null and profile_dislikes.profile_id is null

3
ответ дан 11 февраля 2018 в 06:02 Источник Поделиться