Как получить все элементы, которые добавили действие, но не были удалены - PullRequest
0 голосов
/ 15 марта 2020

У меня есть таблица Activity , в которой сохраняется активность пользователя над действиями. Существует два типа действий в типе столбца, которые необходимо проверить:

  • add_favorite
  • remove_favorite

Таким образом, один и тот же объект может быть добавлен или удален из избранного несколько раз, поэтому в таблице есть такие записи:

| id | type            | timestamp  | object_id | user  |
|----|-----------------|------------|-----------|-------|
| 1  | add_favorite    | 1584150783 | 4         | user1 |
| 2  | add_favorite    | 1584151341 | 5         | user1 |
| 3  | remove_favorite | 1584161259 | 4         | user1 |
| 4  | add_favorite    | 1584168758 | 4         | user1 |
| 5  | remove_favorite | 1584171635 | 10        | user1 |
| 6  | add_favorite    | 1584174201 | 11        | user1 |
| 7  | remove_favorite | 1584177194 | 5         | user1 |

Сначала я строил два запроса, которые собирали все object_id с действиями add_favorite для пользователя в массиве. Затем я отфильтровал этот массив с помощью другого набора object_id, у которого был удален тип действия: _ 1018 *

SELECT object_id FROM activity WHERE user='user1' AND type='add_favorite';
SELECT object_id FROM activity WHERE user='user1' AND type='remove_favorite';

Но это очень неэффективно для большого количества действий. Пожалуйста, посоветуйте мне запрос с LEFT JOIN, который будет более эффективным и даст конечный результат

Ответы [ 2 ]

1 голос
/ 15 марта 2020

Вы можете упростить ваш запрос до:

SELECT object_id
FROM activity
WHERE user = 'user1' AND
      type IN ('add_favorite', 'remove_favorite');

Тогда я бы порекомендовал агрегирование:

SELECT object_id
FROM activity
WHERE user = 'user1' AND
      type IN ('add_favorite', 'remove_favorite')
GROUP BY object_id
HAVING SUM(type = 'add_favorite') > SUM(type = 'remove_favorite');

Получает объекты, которые имеют net больше добавлений, чем удаляет.

В качестве альтернативы можно посмотреть на действие last и выбрать только те из них, которые добавляются:

SELECT a.object_id
FROM activity a
WHERE a.user = 'user1' AND
      a.timestamp = (SELECT MAX(a2.timestamp)
                     FROM activity a2
                     WHERE a2.user = a.user AND
                           a2.type IN ('add_favorite', 'remove_favorite')
                    ) AND
      a.type = 'add_favorite'

С индексом activity(user, type, timestamp) это, вероятно, имеет лучшую производительность.

1 голос
/ 15 марта 2020

Вы можете использовать такой подзапрос, как этот

SELECT object_id
FROM activity a1
WHERE a1.user = 'user1'
AND a1.type = 'add_favorite'
AND object_id NOT IN (
    SELECT object_id
    FROM activity
    WHERE user = 'user1'
        AND type = 'remove_favorite'
    )

Однако, я думаю, вам нужен список эффективно активных (добавленных) избранных

SELECT a1.object_id
FROM activity a1
WHERE a1.user = 'user1'
    AND a1.TIMESTAMP = (
        SELECT MAX(a2.TIMESTAMP)
        FROM activity a2
        WHERE a2.user = a1.user
            AND a1.object_id = a2.object_id
            AND a2.type IN (
                'add_favorite'
                ,'remove_favorite'
                )
        )
    AND a1.type = 'add_favorite'

Вот демо .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...