MySQL переключиться на альтернативную таблицу в зависимости от условий

0

Этот пост длинный, извините за это, но проблема тоже сложная.

Использование mysql и php,
Я могу решить свою проблему с помощью 3 запросов sql, но не в 1, ни в 2.

Итак, почему я размещаю здесь:
кто-нибудь из вас знает способ сделать это менее чем за 3 удара?

(извините за мой английский)

Сначала позвольте мне объяснить контекст:
это о тематическом парке!

Итак, есть владелец тематического парка,
и он владеет тематическим парком с разными зонами, и каждая зона содержит игры.
По словам менеджера игры (человека, ответственного за игру), каждая игра может быть настроена с различными настройками.

Вот что выглядит интересная часть схемы: существует 5 таблиц

themeparkzone
--name (varchar)

themeparkzone_has_game_with_manager
--themeparkzone_id (pk)
--game_id (pk)
--manager_id (fk)
--game_settings (текст)

themeparkzone_has_game
--themeparkzone_id (pk)
--game_id (pk)
--game_settings (текст)

игровые новости --name (varchar)

менеджер
--name (varchar)

В двух таблицах могут потребоваться дополнительные пояснения:

themeparkzone_has_game_with_manager и themeparkzone_has_game.

themeparkzone_has_game может содержать настройки по умолчанию для игр, если владелец themepark написал их.

Затем themeparkzone_has_game_with_manager содержит настройки игры, которые у game_manager есть (или нет),
и эти настройки должны отменять настройки по умолчанию из таблицы themeparkzone_has_game при настройке.

Поскольку владелец themepark хочет, чтобы его themepark был очень привлекательным, он планирует менять настройки каждый день,
и вот соглашение, с которым ему и его команде придется иметь дело:

чтобы решить, какие настройки игры будут применяться,

при запуске мы имеем следующие вары:
- manager_id: например, 22.
- идентификаторы themeparkzone на сегодняшний день, например 12,13,14

Итак, конечная цель:
для данного manager_id, и для данных themeparkzone_ids,
узнать имя и настройки игр,

учитывая, что:
если параметр установлен в файле themeparkzone_has_game_with_manager, он будет применяться остальное
если параметр установлен в themeparkzone_has_game, он будет применяться остальное
нет игры.

Что проблема у меня есть,
и потому, что я не мог сделать это в течение 1 запроса,
Я попробовал первый запрос на цикл themeparkzone_ids,
так что теперь проблема заключается в том, чтобы найти имя и настройки игры для данного менеджера_ид и заданный themeparkzone_id.

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

Мои запросы:

SELECT g.name, w.game_settings
FROM game g
INNER JOIN themeparkzone_has_game_with_manager w на w.game_id = g.id
WHERE w.manager_id = 22
И w.themeparkzone_id в (12,13,14)

и

SELECT g.name, h.game_settings
FROM game g
INNER JOIN themeparkzone_has_game h on h.game_id = g.id
WHERE h.themeparkzone_id в (12,13,14)

Перед ними я помещаю результирующий массив в массив php, а затем смешиваю их в соответствии с конвенциями.

Итак, мне было интересно, есть ли один способ решить условия в запросе mysql вместо того, чтобы делать это с помощью php.

Запрос, который сделает что-то вроде этого:
foreach (themeparkzone_id и manager_id)
если существует соответствующий параметр в themeparkzone_has_game_with_manager
takeit,
остальное
если существует соответствующая настройка в themeparkzone_has_game
takeit,
остальное
takenothing.

Надеюсь, кто-то понял, что я пытался объяснить.

  • 1
    Есть ли действительно веская причина сделать это в MySQL вместо PHP, где это уже работает? У вас есть проблемы с производительностью? Мне трудно представить, что это стоит потраченных усилий, пытаясь проникнуть в mySQL - сделать это условием запроса, независимо от того, существует таблица или нет, для меня она не соответствует духу mySQL.
Теги:

3 ответа

2
Лучший ответ

Учитывая ваш макет базы данных, я думаю, что было бы лучше изменить некоторые вещи.

Я бы поставил themeparkzone_has_game_with_manager и themeparkzone_has_game_with_manager в одну таблицу. Затем я создам новую таблицу games_managers, которая устанавливает соединение, управление которым может управлять менеджерами.

Тогда я думаю, это должно быть возможно сделать с меньшим количеством запросов.

Обратите внимание, что вам нужно разобраться с деталями для себя, т.е. вы можете указать флаг для каждой игры, если у него должен быть менеджер или нет, и т.д.

  • 0
    Я согласен с этим (хотя я думаю, что вы имели в виду ссылки на разные имена таблиц, поэтому вы, возможно, захотите немного отредактировать свой ответ). Имейте одну таблицу с дополнительным логическим полем, указывающим, было ли это установлено менеджером или нет.
  • 1
    @Nick Если мы установим логическое поле, которое задает менеджер, то настройки по умолчанию для этой игры будут потеряны.
Показать ещё 2 комментария
0

Ура,
Наконец я нашел поворот,
это немного грязно для новичка, как я, но он работает, и... только результаты имеют значение...

Вот запрос, который соответствует моим потребностям:
спасибо всем за вашу помощь:

SELECT
    сливаться (g.name, g2.name),
    coalesce (w.params, h.params)
ОТ
    themeparkzone z
LEFT JOIN themeparkzone_has_game_with_manager w ON w.themeparkzone_id = z.id AND w.manager_id = 2
LEFT JOIN themeparkzone_has_game h на h.themeparkzone_id = z.id
LEFT JOIN game g ON g.id = w.game_id
Игра LEFT JOIN g2 ON g2.id = h.game_id WHERE z.id in (12,13,14)

Таким образом, этот запрос получает результат в таблице themeparkzone_has_game_with_manager, и если они не основаны, попробуйте извлечь результат из themeparkzone_has_game и если они не основаны, все равно верните нулевой результат.
Надеюсь, это поможет кому-то.

  • 0
    Ой, наконец, это не удается! Сдаваясь сейчас, делаю это в 3 запроса ...
0

Вы можете сделать это, используя LEFT JOIN и COALESCE.

SELECT
    g.name,
    COALESCE(w.game_settings, h.game_settings)
FROM
    game AS g
    INNER JOIN themeparkzone_has_game AS h ON h.game_id = g.id
    LEFT JOIN themeparkzone_has_game_with_manager AS w ON
        w.game_id = g.id AND
        w.themeparkzone_id = h.themeparkzone_id AND
        w.manager_id = 22
WHERE
    h.themeparkzone_id IN (12, 13, 14)

В отличие от INNER JOIN, a LEFT JOIN всегда содержит по крайней мере одну строку для каждой строки в левой таблице, даже если в правой таблице нет строк, соответствующих условиям соединения. В этом случае столбцы из правой таблицы будут NULL. COALESCE() возвращает первое значение, отличное от NULL, с которым он поставляется, поэтому, если в themeparkzone_has_game_with_manager нет соответствующих строк, он вернет значение game_settings из themeparkzone_has_game.

  • 0
    Это не сработало, как ожидалось (получил пустой результат), но я собираюсь обойти это внутреннее соединение, левое соединение и объединить вещи, это звучит хорошо. Thanx.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню