Я думал, что понял, как работают левые внешние соединения, но у меня есть ситуация, которая не работает, и я не на 100% уверен, неправильный ли способ структурирования моего запроса или проблема с данными.
Для справки, у меня есть следующие структуры таблиц MySQL:
mysql> describe achievement;
+-------------+----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------------------+------+-----+---------+-------+
| id | varchar(64) | NO | PRI | NULL | |
| game_id | varchar(10) | NO | PRI | NULL | |
| name | varchar(64) | NO | | NULL | |
| description | varchar(255) | NO | | NULL | |
| image_url | varchar(255) | NO | | NULL | |
| gamerscore | smallint(5) unsigned | NO | | 0 | |
| hidden | tinyint(1) | NO | | 0 | |
| base_hidden | tinyint(1) | NO | | 0 | |
+-------------+----------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)
и
mysql> describe gamer_achievement;
+----------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------+-------+
| game_id | varchar(10) | NO | PRI | NULL | |
| achievement_id | varchar(64) | NO | PRI | NULL | |
| gamer_id | varchar(36) | NO | PRI | NULL | |
| earned_epoch | bigint(20) unsigned | NO | | 0 | |
| offline | tinyint(1) | NO | | 0 | |
+----------------+---------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
Что касается данных, я здесь ввел вот что (только соответствующие столбцы включены для краткости):
+----+------------+------------------------------+
| id | game_id | name |
+----+------------+------------------------------+
| 1 | 1480656849 | Cluster Buster |
| 2 | 1480656849 | Star Gazer |
| 3 | 1480656849 | Flower Child |
| 4 | 1480656849 | Oyster-meister |
| 5 | 1480656849 | Big Cheese of the South Seas |
| 6 | 1480656849 | Hexic Addict |
| 7 | 1480656849 | Collapse Master |
| 8 | 1480656849 | Survivalist |
| 9 | 1480656849 | Tick-Tock Doc |
| 10 | 1480656849 | Marathon Mogul |
| 11 | 1480656849 | Millionaire Extraordinaire |
| 12 | 1480656849 | Grand Pearl Pooh-Bah |
+----+------------+------------------------------+
12 rows in set (0.00 sec)
и
+----------------+------------+--------------+---------+
| achievement_id | game_id | earned_epoch | offline |
+----------------+------------+--------------+---------+
| 1 | 1480656849 | 0 | 1 |
| 2 | 1480656849 | 0 | 1 |
| 3 | 1480656849 | 0 | 1 |
| 4 | 1480656849 | 1149789371 | 0 |
| 7 | 1480656849 | 1149800406 | 0 |
| 8 | 1480656849 | 0 | 1 |
| 9 | 1480656849 | 1149794790 | 0 |
| 10 | 1480656849 | 1149792417 | 0 |
+----------------+------------+--------------+---------+
8 rows in set (0.02 sec)
В В данном конкретном случае таблица достижений
является «главной» таблицей и будет содержать информацию, которую я всегда хочу видеть.Таблица gamer_achievement
содержит информацию только о фактически заработанных достижениях. Для любой конкретной игры для любого конкретного игрока может быть любое количество строк в таблице gamer_achievement
, включая ни одной, если в этой игре не было заработано никаких достижений. Например, в приведенном выше примере данных достижения с идентификаторами 5, 6, 11 и 12 не были получены.
В настоящее время я написал
select a.id,
a.name,
ga.earned_epoch,
ga.offline
from achievement a
LEFT OUTER JOIN gamer_achievement ga
ON (a.id = ga.achievement_id and a.game_id = ga.game_id)
where ga.gamer_id = 'fba8fcaa-f57b-44c6-9431-4ab78605b024'
and a.game_id = '1480656849'
order by convert (a.id, unsigned)
, но это возвращает только полную информацию для тех достижений, которые фактически были заработаны - информация о незаработанных достижениях из правой таблицы ( gamer_achievement
) не отображается. показать со значениями NULL, как я ожидал от этого типа запроса. Вот что я ожидаю увидеть:
+----+-------------------------------+--------------+---------+
| id | name | earned_epoch | offline |
+----+-------------------------------+--------------+---------+
| 1 | Cluster Buster | 0 | 1 |
| 2 | Star Gazer | 0 | 1 |
| 3 | Flower Child | 0 | 1 |
| 4 | Oyster-meister | 1149789371 | 0 |
| 5 | Big Cheese of the South Seas | NULL | NULL |
| 6 | Hexic Addict | NULL | NULL |
| 7 | Collapse Master | 1149800406 | 0 |
| 8 | Survivalist | 0 | 1 |
| 9 | Tick-Tock Doc | 1149794790 | 0 |
| 10 | Marathon Mogul | 1149792417 | 0 |
| 11 | Millionaire Extraordinaire | NULL | NULL |
| 12 | Grand Pearl Pooh-Bah | NULL | NULL |
+----+-------------------------------+--------------+---------+
12 rows in set (0.00 sec)
Что мне здесь не хватает? Насколько я понимаю, основной запрос ВЫГЛЯДИТ мне прямо, но мне явно не хватает какой-то важной информации.
Многие ответили, но я тоже попробую и, надеюсь, внесу еще несколько уточнений. Как я всегда интерпретировал это (и вы можете проверить так много других постов, на которые я ответил с помощью ЛЕВЫХ объединений), я пытаюсь перечислить таблицу, в которой я хочу все сначала (слева ... отсюда читаем слева направо). Затем левое соединение с таблицей «Другое» (правая сторона) при любых критериях между ними ... Затем, при выполнении левого соединения и при наличии дополнительных критериев относительно правой таблицы эти условия остаются с этим условием соединения. , Включение их в предложение «WHERE» подразумевает ВНУТРЕННЕЕ СОЕДИНЕНИЕ (должно всегда совпадать), что не то, что вы хотите ... Я также стараюсь всегда показывать левую таблицу alias.field = правая таблица alias.field, чтобы сохранить корреляцию clear ... Затем примените предложение where к базисным критериям, которые вы хотите получить из первой таблицы .. что-то вроде
select
a.id,
a.name,
ga.earned_epoch,
ga.offline
from
achievement a
LEFT OUTER JOIN gamer_achievement ga
ON a.id = ga.achievement_id
AND a.game_id = ga.game_id
AND ga.gamer_id = 'fba8fcaa-f57b-44c6-9431-4ab78605b024'
where
a.game_id = '1480656849'
order by
convert (a.id, unsigned)
Обратите внимание на прямую связь между «a» и «ga» по общему идентификатору и значения идентификатора игры, но затем привязывается к конкретному игроку. Предложение where касается только внешнего уровня достижений, основанного на конкретной игре.