MySQL объединяет таблицы СЛЕВА или PHP объединяет массивы

#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. Это не сработает, если в городе есть записи в отправлениях, просто не в запрошенную дату (например, Рим в примере начала темы)