#php #mysql #sql #arrays #join
#php #mysql #sql #массивы #Присоединиться
Вопрос:
Я застрял, и мне нужна ваша помощь (совет). Я использую PHP и MySQL, и моя проблема представлена ниже.
Это упрощенная версия того, чего я пытаюсь достичь. У меня есть две таблицы, одна из которых — список городов, а другая — отправления. Я хотел бы объединить эти две таблицы слева (если возможно) и вернуть список всех городов, даже если в таблице bus_departures нет связанных записей.
Могу ли я сделать это, используя только MySQL, или мне придется объединять массивы в PHP. Я хотел бы увидеть ваше решение. Спасибо.
Город
-------------------
ID | CITY
-------------------
1 | London
2 | Paris
3 | New York
4 | Rome
5 | Zagreb
Bus_Departures
------------------------------------------
ID | DATE | CITY | No. DEPARTURES
------------------------------------------
1 | 2016-06-06 | 1 | 5
2 | 2016-06-06 | 4 | 3
3 | 2016-06-06 | 3 | 2
4 | 2016-06-07 | 3 | 4
5 | 2016-06-07 | 1 | 1
6 | 2016-06-08 | 3 | 8
7 | 2016-06-09 | 1 | 3
8 | 2016-06-09 | 4 | 2
ВЫБЕРИТЕ
SELECT * FROM City LEFT JOIN Bus_Departures WHERE date = '2016-06-07' ORDER BY City ASC
ВОЗВРАТ
London 2016-06-07 1
New York 2016-06-07 4
Я ХОТЕЛ БЫ ПОВТОРИТЬ ЭТО ПОЛЬЗОВАТЕЛЮ
London 2016-06-07 1
New York 2016-06-07 4
Paris 2016-06-07 - (no records at all)
Rome 2016-06-07 - (no records for this day)
Zagreb 2016-06-07 - (no records at all)
Спасибо!
Комментарии:
1. Вы сделали чрезвычайно трудным для любого копирование вставки ваших данных / таблиц. Пожалуйста, разместите их как два отдельных раздела, а не рядом. Также номера сообщений вместо 1 (лондон) и т. Д. Мы можем это выяснить, спасибо
2. Левое соединение в порядке, но ваш оператор WHERE находится в таблице с правой стороны после
left join
выполнения. В результате, например, ваша запись joined Paris будет выглядеть какParis NULL NULL
и не будет выбрана, точно так же, как две записи Rome, которые будут выглядеть какRome 2016-06-06 3
иRome 2016-06-09 2
.3. спасибо за критику e4c5, в следующий раз я постараюсь опубликовать более удобные для пользователя таблицы! еще раз спасибо Elijan9.
Ответ №1:
Вам, конечно, нужно сделать a LEFT JOIN
для вашего варианта использования, но в вашем текущем заявлении ваше WHERE
заявление будет выполняться для уже объединенной таблицы. Таким образом, прямо перед WHERE
использованием предложения уже объединенная таблица будет выглядеть так:
London | 2016-06-06 | 5
Rome | 2016-06-06 | 3
New York | 2016-06-06 | 2
New York | 2016-06-07 | 4
London | 2016-06-07 | 1
New York | 2016-06-08 | 8
London | 2016-06-09 | 3
Rome | 2016-06-09 | 2
Paris | NULL | NULL
Zagreb | NULL | NULL
Теперь очевидно, что a WHERE date = '2016-06-07'
не вернет нужные вам данные.
Однако это будет работать, если вы включите свое требование о дате в предложение join, например:
SELECT * FROM City LEFT JOIN Bus_Departures
ON (City.ID = Bus_Departure.CITY AND Bus_Departure.date = '2016-06-07')
ORDER BY City ASC
В этом случае LEFT JOIN
выполняется только это с правой стороны:
------------------------------------------
ID | DATE | CITY | DEPARTURES
------------------------------------------
4 | 2016-06-07 | 3 | 4
5 | 2016-06-07 | 1 | 1
(Это также будет работать быстрее.)
Поскольку вы также хотите, чтобы дата была включена в ваш результат, полное утверждение может выглядеть следующим образом:
SELECT City.CITY, '2016-06-07', Bus_Departure.DEPARTURES
FROM City LEFT JOIN Bus_Departures
ON (City.ID = Bus_Departure.CITY AND Bus_Departure.date = '2016-06-07')
ORDER BY City.ID ASC
Комментарии:
1. Вы мне очень помогли, Elijan9, спасибо! Это ИМЕННО то, что мне было нужно, и вы даже объяснили это шаг за шагом! Спасибо
Ответ №2:
Когда вы выполняете предложение where, которое вы ограничиваете датой, вы избавляетесь от всех нулевых значений. Если вы хотите по-прежнему видеть их в своем результате, вам нужно включить проверку null в свой запрос.
select c.CITY, bd.DATE, bd.DEPARTURES from city c
left join bus_departures as bd on bd.city = c.id
where bd.DATE='2016-06-07' or bd.DATE is null;
Комментарии:
1. Это не сработает, если в городе есть записи в отправлениях, просто не в запрошенную дату (например, Рим в примере начала темы)