MySQL - выбор строк на основе условий - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть запрос, который выбирает пользователей из таблицы members, если mem_id не существует в таблице swipes. Запрос выглядит следующим образом:

SELECT members.* FROM members
WHERE NOT EXISTS (SELECT * FROM swipes WHERE (mem_id IN (swp_by, swp_to) AND :mem IN (swp_by)))

Приведенный выше запрос выполняет половину моей работы. Однако я хочу добавить еще пару условий здесь. В таблице swipes есть два поля, а именно swp_type и swp_status. Здесь swp_type имеет ENUM значения left, right, top, которые показывают, что карта прошла слева, справа или сверху (как трут), а swp_status также имеет ENUM значения requested, accepted, declined, unmatched, которая указывает, что запрошенный друг все еще запрашивается Государство, или принято, или отклонено, или позже, после принятия не имеет себе равных. Теперь я хочу изменить приведенный выше запрос, чтобы он принимал эти две таблицы в условиях и возвращал результат на их основе.

Давайте рассмотрим пример:

Допустим, есть два пользователя 1 и 2. Сейчас в таблице swipes нет записей, чтобы пользователи 1 и 2 могли видеть друг друга.

Теперь, скажем, если пользователь 1 УДАЛ ЛЕВЫЙ пользователь 2, то:

swp_by: 1, swp_to: 2, swp_type: left, swp_status: requested

Для приведенных выше данных пользователь 1 УДАЛ ЛИСТ пользователь 2 (что означает, что пользователь 1 не хочет совпадать с пользователем 2) чтобы они больше не могли видеть друг друга.

Теперь, скажем, если пользователь 1 правый или верхний пользователь 2, то:

swp_by: 1, swp_to: 2, swp_type: right/top, swp_status: requested

Для приведенных выше данных пользователь 1 больше не может видеть пользователя 2, но пользователь 2 может видеть пользователь 1 как swp_type здесь прав, а swp_status равен requested.

Теперь, скажем, для приведенных выше данных swp_status не requested, но все остальное, кроме requested скажем (принято) / отказался), тогда оба пользователя больше не смогут видеть друг друга. Это то, что я хочу добавить в свой текущий запрос в качестве условия.

Мой текущий запрос выполняет половину работы, отображая членов, которых нет в таблице swipes с учетом swp_by & swp_to. Я хочу добавить условия для swp_type и swp_status, как описано выше.

Что я пробовал?

Я попробовал следующее, но в итоге получаю странные результаты. Он вернул все элементы, когда в соответствии с данными он должен возвращать элемент только с mem_id 8, так как он не существует в таблице смахиваний по отношению к пользователю 1 и пользователю 12, как это right и requested и пользователь 15 как есть top и requested.

SELECT * FROM members
WHERE NOT EXISTS (SELECT * FROM swipes WHERE (mem_id IN (swp_by, swp_to) AND 1 IN (swp_by)) AND swp_type != 'left' AND swp_status = 'requested')

Следовательно, я думаю, что это не то, как я должен размещать условия.

Fiddle Here: DB FIDDLE

1 Ответ

1 голос
/ 25 апреля 2020

Я выхожу на конечность, потому что, признаюсь, мне было очень тяжело следовать вашим объяснениям. В конце концов я понятия не имел, описали ли вы обработку кредитной карты, службу знакомств или что-то еще. Поэтому вам, возможно, придется «настроить» SQL на основе любого недопонимания, которое у меня может быть.

Чтобы лучше понять мои SQL, я взял ваш исходный SQL:

SELECT members.* FROM members
WHERE NOT EXISTS (SELECT * FROM swipes WHERE (mem_id IN (swp_by, swp_to) AND 1 IN (swp_by)))

и пересчитать его до того, что я считаю эквивалентным, и использовать его в качестве отправной точки:

SELECT members.* FROM members
WHERE mem_id <> 1
AND NOT EXISTS (
  SELECT * FROM swipes WHERE mem_id = swp_to AND swp_by = 1
)

В итоге я получил:

SELECT * from members
WHERE mem_id <> 1
AND NOT EXISTS (
  SELECT * FROM swipes WHERE
      members.mem_id = swp_by and 1 = swp_to OR
      members.mem_id = swp_to and 1 = swp_by
)
UNION
SELECT * FROM members
WHERE mem_id <> 1
AND EXISTS (
  SELECT * FROM swipes WHERE swp_by = members.mem_id AND swp_to = 1
  AND swp_type <> 'left' AND swp_status = 'requested'
)

Это объединение. Первая часть:

SELECT * from members
WHERE mem_id <> 1
AND NOT EXISTS (
  SELECT * FROM swipes WHERE
      members.mem_id = swp_by and 1 = swp_to OR
      members.mem_id = swp_to and 1 = swp_by
)

Это попытка выбрать все строки, которые «не существуют в таблице смахиваний по отношению к пользователю 1», что будет с вашими примерами данных mem_id 8. Теперь, возможно, следует проверять только swp_by=1 и swp_to=8, а не * swp_by=8 и swp_to=1 (или наоборот). Если это так, вы можете выполнить эту настройку.

Второй фрагмент объединения добавляет строки, имеющие соответствующий удар (swp_by установлен на mem_id) с swp_type, не равным 'left' и swp_status равно 'requested' с swp_to равно 1. Я использовал этот критерий на основе ваших выборочных данных и строк, которые вы ожидали вернуть:

SELECT * FROM members
WHERE mem_id <> 1
AND EXISTS (
  SELECT * FROM swipes WHERE swp_by = members.mem_id AND swp_to = 1
  AND swp_type <> 'left' AND swp_status = 'requested'
)

Если SQL не совсем то, что вам нужно, я думаю, что требуется лишь небольшая корректировка .

См. Db-Fiddle

Вышесказанное также может быть выполнено с использованием внутренних и внешних соединений:

SELECT members.* from members LEFT JOIN swipes ON
  mem_id = swp_by AND 1 = swp_to OR
  mem_id = swp_to and 1 = swp_by
WHERE mem_id <> 1 AND swp_id is NULL
UNION
SELECT DISTINCT members.* FROM members JOIN swipes ON
  mem_id = swp_by AND
  swp_to = 1 AND
  swp_type <> 'left' AND
  swp_status = 'requested'
WHERE mem_id <> 1

DB-Fiddle

Глядя на вышесказанное, можно предположить, что есть возможность удалить объединение:

SELECT DISTINCT members.* from members LEFT JOIN swipes ON
  mem_id = swp_by AND 1 = swp_to OR
  mem_id = swp_to AND 1 = swp_by
WHERE mem_id <> 1 AND
  swp_id is NULL OR (
    mem_id = swp_by AND
    swp_to = 1 AND  
    swp_type <> 'left' AND
    swp_status = 'requested'
  )
ORDER BY mem_id

DB-Fiddle

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