2013-04-12 2 views
0

У меня есть три стола: orders, user_addresses и alternate_addresses. Пользователь всегда имеет user_address. Заказ имеет номер alternate_address_id, который может содержать alternate_address_id или NULL.Есть ли лучший способ использовать значения из таблицы a или таблицы b?

Сейчас мой запрос выглядит следующим образом:

SELECT 
    IF(ISNULL(orders.alternate_address_id), a.firstname, u.firstname) AS firstname, 
    IF(ISNULL(orders.alternate_address_id), a.lastname, u.lastname) AS lastname 
    -- etc. 
FROM orders 
LEFT JOIN alternate_addresses a ON (
    orders.alternate_address_id IS NOT NULL 
    AND orders.alternate_address_id = a.alternate_address_id) 
LEFT JOIN user_addresses u ON (
    orders.alternate_address_id IS NULL 
    AND orders.user_id = u.user_id) 

Это кажется отчасти излишним делать IF(ISNULL()) части для каждого поля адреса, так как я знаю, какой адрес мне нужно использовать после первой.

Есть ли лучший способ сделать это (я не могу изменить дизайн таблиц)?

Спасибо за ваши мысли .

+0

[COALESCE()?] (Http://dev.mysql.com/doc/refman/5.0/ru/comparison-operators.html#function_coalesce) –

+0

Я считал это. Но если альтернативный_адрес не имел, допустим, имя_компании, он будет смешиваться в возможном user_addresses.company_name, что будет проблемой. – Chris

+0

Вы говорите, что вы не можете изменить дизайн стола. Можете ли вы по крайней мере изменить логику приложения, чтобы каждый заказ имел альтернативный_адрес (который по умолчанию совпадает с user_address)? Я думаю, что это еще лучше в логических терминах, поскольку ваши прошлые заказы будут иметь адрес, куда они были отправлены, даже если пользователь изменит свой текущий адрес позже. –

ответ

1

Настоящая проблема заключается в том, что user_addresses и alternate_addresses - это разные таблицы. Поскольку они представляют собой разные таблицы, будет сложно заставить SQL обрабатывать их равномерно.

Было бы намного лучше иметь единую таблицу адресов, на которую могут ссылаться пользователи и (необязательно) по заказам, и тогда вы сможете разработать условие JOIN, которое присоединилось бы к правильному адресу для каждого заказ.

+0

Хотя это может быть правдой, это не вариант изменения дизайна db. И ваш ответ будет лучше подходит в разделе комментариев. Спасибо, в любом случае. – Chris

+0

По какой-то причине людям не нравится 'UNION', но это мощный инструмент, который позволяет вам не вытеснять разнородные данные в одну уродливую таблицу с тоннами столбцов NULL. –

+0

Конечно, но не было никаких доказательств в вопросе, что user_addresses и alternate_addresses на самом деле были неоднородными: из информации, которую мы имели, казалось, что они были похожими/одинаковыми. Конечно, вы можете ПРИСОЕДИНЯТЬСЯ к UNION user_addresses + alternate_addresses в полной базе данных SQL; Я не уверен, может ли mysql это сделать. – drquicksilver

1
SELECT a.firstname AS firstname, a.lastname AS lastname, ... 
FROM orders 
JOIN alternate_addresses a ON (orders.alternate_address_id = a.alternate_address_id) 

UNION 

SELECT u.firstname AS firstname, u.lastname AS lastname, ... 
FROM orders 
LEFT JOIN user_addresses u ON (orders.user_id = u.user_id) 
WHERE orders.alternate_address_id IS NULL 

Собственно, у drquicksilver есть смысл. Было бы лучше иметь в таблице addresses дополнительную колонку для типа адреса (основной, альтернативный вариант, что еще?). Теперь alternate_address_id не требуется, вместо этого вы ссылаетесь на один из адресов пользователя. FOREIGN KEY (user_id, address_id) REFERENCES addresses (user_id, address_id), или что-то в этом роде.

+0

Спасибо. На самом деле это не решение проблемы? Это дало бы мне два набора результатов, которые мне пришлось бы выбирать между программным кодом. – Chris

+0

Нет, это дает вам * один * результирующий набор. 'UNION' - оператор SQL. –

+0

Извините, неправильный термин. Один набор результатов, 2 "строки" в результирующем наборе. – Chris

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