Этот пост длинный, извините за это, но проблема тоже сложная.
Использование 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.
Надеюсь, кто-то понял, что я пытался объяснить.
Учитывая ваш макет базы данных, я думаю, что было бы лучше изменить некоторые вещи.
Я бы поставил themeparkzone_has_game_with_manager
и themeparkzone_has_game_with_manager
в одну таблицу. Затем я создам новую таблицу games_managers
, которая устанавливает соединение, управление которым может управлять менеджерами.
Тогда я думаю, это должно быть возможно сделать с меньшим количеством запросов.
Обратите внимание, что вам нужно разобраться с деталями для себя, т.е. вы можете указать флаг для каждой игры, если у него должен быть менеджер или нет, и т.д.
Ура,
Наконец я нашел поворот,
это немного грязно для новичка, как я, но он работает, и...
только результаты имеют значение...
Вот запрос, который соответствует моим потребностям:
спасибо всем за вашу помощь:
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
и если они не основаны, все равно верните нулевой результат.
Надеюсь, это поможет кому-то.
Вы можете сделать это, используя 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
.