2014-10-25 3 views
0

У меня есть две таблицы:Как присоединиться к столам с объединением? MySQL

  1. истории
  2. бизнес

Я хочу, чтобы запустить этот запрос:

SELECT name, talias.* 
FROM 
    (SELECT business.bussName as name history.* 
     FROM history 
     INNER JOIN business on history.bussID = business.bussID 
     WHERE history.activity = 'Insert' OR history.activity = 'Update' 
    UNION 
     SELECT name as Null, history.* 
     FROM history 
     WHERE history.activity = 'Delete' 

    ) as talias 
WHERE 1 
order by talias.date DESC 
LIMIT $fetch,20 

этот запрос принять 13 вторых, я думаю, что проблема что Mysql объединяет все строки в истории и бизнес-таблицах! Пока он должен присоединиться всего к 20 рядам!

Как я могу это исправить?

+0

Вы видите что-то странное в этом запросе? – Strawberry

+0

Да! mysql присоединяется к двум большим таблицам, а просто присоединяется к 20 строкам! – david

+0

Он не может получить только 20 строк, потому что он должен выполнять 'JOIN' и' UNION', прежде чем он выполнит 'ORDER BY'. – Barmar

ответ

0

Если я вас правильно понял вы хотите, чтобы все строки из истории, где активность deleted плюс все те строки, в которых деятельность является «Insert» или «Обновить» и есть соответствующая строка в таблице бизнес.

Я не знаю, будет ли это быстрее вашего запроса - вам нужно будет проверить план выполнения, чтобы проверить это.

SELECT * 
FROM history 
where activity = 'Delete' 
    or ( activity in ('Insert','Update') 
     AND exists (select 1 
        from business 
        where history.bussID = business.bussID)) 
order by `date` DESC 
LIMIT $fetch,20 

Редактировать (после того, как вопрос изменился)

Если вам нужны столбцы из бизнес-таблицы, заменив union с внешним соединением может повысить производительность.

Но, честно говоря, я этого не ожидаю. Оптимизатор MySQL не очень умный, и я не удивлюсь, если внешнее соединение было фактически реализовано с использованием своего рода объединения. Опять же, вы можете проверить это, посмотрев план выполнения.

SELECT h.*, 
     b.bussName as name 
FROM history 
    LEFT JOIN business b 
     ON h.bussID = b.bussID 
     AND h.activity in ('Insert','Update') 
WHERE h.activity in ('Delete', 'Insert','Update') 
ORDER BY h.`date` DESC 
LIMIT $fetch,20 

Btw: date это ужасное имя столбца. Во-первых, потому что это зарезервированное слово, второе (и более важное), потому что оно ничего не документирует. Это «дата создания»? «Дата удаления»? «Срок оплаты»? Некоторая другая дата?

+0

Благодарим вас за ответ, дата - дата создания, но я также хочу получить business.name из бизнес-таблицы при вводе или обновлении активности. Как я могу это сделать? – david

+0

теперь лучше, потребовалось всего 0,1535 секунды. поэтому, когда я должен использовать союз и когда я должен использовать левое соединение? союз плох? могу ли я удалить весь союз из моего проекта! – david

+0

@ david: Мне почти никогда не приходится использовать MySQL, поэтому я не могу сказать. –

0

Попробуйте это:

SELECT h.* 
FROM history AS h 
WHERE (h.activity IN ('Insert', 'Update') 
     AND EXISTS (SELECT * FROM business AS b WHERE b.bussID = h.bussID)) 
    OR h.activity = 'Delete' 
ORDER BY h.date DESC 
LIMIT $fetch, 20 

Для ORDER BY и LIMIT, чтобы быть эффективными, убедитесь, что у вас есть индекс по history.date.

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