2016-01-28 3 views
0

У меня есть несколько таблиц - User/event/booking/location - из которых мне нужно собрать данные.SQL-запрос с несколькими таблицами и объединениями

У меня нет навыков SQL, и я просто пытаюсь сшить что-то вместе. До сих пор я могу получить все пользовательские данные и данные бронирования с помощью следующего запроса:

SELECT ds_usermeta.first_name, ds_usermeta.last_name, 
     ds_usermeta.phone_number, ds_usermeta.mobile_number, ds_usermeta.user_emerg_name, 
     ds_usermeta.user_emerg_rel, ds_usermeta.user_emerg_phone, 
     ds_em_bookings.booking_date, ds_em_bookings.booking_comment 

FROM 
(
    SELECT user_id, 
     MAX(CASE WHEN meta_key = 'first_name' THEN meta_value END) first_name, 
     MAX(CASE WHEN meta_key = 'last_name' THEN meta_value END) last_name, 
     MAX(CASE WHEN meta_key = 'phone_number' THEN meta_value END) phone_number, 
     MAX(CASE WHEN meta_key = 'mobile_number'  THEN meta_value END) mobile_number, 
     MAX(CASE WHEN meta_key = 'user_emerg_name'  THEN meta_value END) user_emerg_name, 
     MAX(CASE WHEN meta_key = 'user_emerg_rel'  THEN meta_value END) user_emerg_rel, 
     MAX(CASE WHEN meta_key = 'user_emerg_phone'  THEN meta_value END) user_emerg_phone 
    FROM ds_usermeta 
    WHERE EXISTS 
    (
     SELECT * 
     FROM ds_em_bookings 
     WHERE ds_em_bookings.person_id = ds_usermeta.user_id 
) 
    GROUP BY ds_usermeta.user_id 
) ds_usermeta JOIN ds_em_bookings 
    ON ds_usermeta.user_id = ds_em_bookings.person_id 
    ORDER BY ds_em_bookings.event_id 

Поскольку пользовательские данные хранятся в строках он не может быть просто SELECTED - пример пользователя Meta таблицы данных:

umeta_id user_id meta_key meta_value 
----------------------------------------------- 
    1   1  nickname mikesmith 
    2   1  first_name Mike 
    3   1  last_name Smith 

Моя проблема заключается в том, что данные бронирования в ds_em_bookings - это всего лишь идентификаторы. Чтобы получить «хорошее имя», мне нужно вытащить его из ds_em_events, сопоставляя ID. Мне также нужно вывести имя местоположения из ds_em_locations, сопоставляя ID с ds_em_events.

Тогда я надеюсь, что-то вроде этого

First_name | Last_name | booking_date | event_name | location_name 

только со всеми пользовательскими полями выше. Я попробовал несколько комбинаций, основанных на этом:

(
    SELECT event_name 
    FROM ds_em_events 
    WHERE ds_em_events.event_id = ds_em_bookings.event_id 
    JOIN ds_em_bookings 
    ON ds_em_events.event_id = ds_em_bookings.event_id 
) 
(
    SELECT location_name 
    FROM ds_em_locations 
    WHERE ds_em_locations.location_id = ds_em_events.location_id 
    LEFT JOIN ds_em_events 
    ON ds_em_locations.location_id = ds_em_events.location_id 

) 

Но не может работать, как/где поместить это или что-то подобное, чтобы вытащить EVENT_NAME от ds_em_events и местоположение (идентификатор, для которого находится в таблице ds_em_events) для каждого бронирования, которое найдено.

Извините, это длинный пост, но я надеюсь, что этого достаточно, чтобы быть понятным. Любая помощь приветствуется - пожалуйста, помните, что я новичок, просто начиная с SQL.

+0

Добро пожаловать в SO, Майк. Я хотел бы предложить вам сделать [SQL Fiddle] (http://sqlfiddle.com/) и опубликовать его, чтобы мы могли видеть ваши таблицы и иметь некоторые примеры данных. – MyBrainHurts

+0

Это, несомненно, облегчило бы ответ! :) Это простая проблема, но имена и структура этих таблиц ужасны ... – Boris

ответ

1

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

SELECT ds_usermeta.first_name, 
     ds_usermeta.last_name, 
     ... 
     ds_em_bookings.booking_date, 
     ds_em_bookings.booking_comment, 
     ds_em_events.event_name, 
     ds_em_locations.location_name 

FROM 
    (SELECT user_id, 
     MAX(CASE WHEN meta_key = 'first_name' THEN meta_value END) first_name, 
     MAX(CASE WHEN meta_key = 'last_name' THEN meta_value END) last_name, 
     ... 
     FROM ds_usermeta 
     GROUP BY ds_usermeta.user_id 
    ) ds_usermeta 
INNER JOIN ds_em_bookings ON ds_usermeta.user_id = ds_em_bookings.person_id 
INNER JOIN ds_em_events ON ds_em_events.event_id = ds_em_bookings.event_id 
INNER JOIN ds_em_locations ON ds_em_locations.location_id = ds_em_events.location_id 
ORDER BY ds_em_bookings.event_id 

Обратите внимание, что если у вас есть JOIN вы не должны также должны сравните идентификаторы в предложении WHERE. Используйте INNER JOIN вместо WHERE EXISTS, потому что это устранит все строки, в которых нет соответствующей строки в другой таблице.

Также обратите внимание, что LEFT JOIN отобразит все строки из левой таблицы - если в правой таблице нет соответствующей строки, она отобразит NULL. Обратите внимание на незначительную разницу в примере. Вы сделали:

SELECT location_name 
FROM ds_em_locations 
LEFT JOIN ds_em_events ON ds_em_locations.location_id = ds_em_events.location_id 

, которая соединяет события в местах и ​​дает вам все места, даже те, которые не имеют никаких событий - однако ваш главный запрос в другую сторону, так что мы делаем

JOIN ds_em_locations ON ds_em_locations.location_id = ds_em_events.location_id 

который присоединяется к местам событий/заказов, чтобы они не отображали места без заказов. Если вы хотите показать все такие строки, вам может понадобиться сделать RIGHT JOIN или подобное.

The Wiki article on JOINs очень тщательный - прочитайте его!

+0

Спасибо, Борис - это сработало отлично. Здесь вы были спасателем жизни. Очень признателен. –

Смежные вопросы