Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Добрый день, друзья! уже продолжительное время бьюсь над этой задачей.
Задача:
Есть 2 таблицы A и Б, одной записи из A соответствует несколько из Б. Нужно соединить таблицы таким образом чтобы для каждой из A выбрать только максимальную по дате из Б.
Заранее благодарю за помощь!!!
Банальный пример
Таблица A
id name
1 Иван
2 Петя
3 Сидор
Таблица Б
surname date A.id
Иванов 5июня 1
Петров 6июня 1
Сидоров 5мая 2
Рыбкин 6мая 2
На выходе получаем
1 Иван Петров 6июня 1
2 Петя Рыбкин 6мая 2
3 Сидор NULL NULL NULL
Неактивен
Неактивен
А почему
Неактивен
короче на 3 символа
Неактивен
Больше интересует, почему работает? +)))
Неактивен
в order by и group by можно указывать не имя колонки, а её порядковый номер из части перечисления полей после select
Неактивен
vasya написал:
select a.id, b.surname, t.d from `таблица А` left join
(select `A.id` id, max(`date`) d from `таблица Б` group by 1) t on a.id=t.id
left join `таблица Б` b on t.id=b.`A.id` and t.d=b.`date`;
Можешь пожалуйста объяснить свой запрос, если не сложно. Просто работаю с SQL на уровне простых запросов, поэтому не совсем понятно. Выводит так же ошибку #1054 - Unknown column 'A.id' in 'field list'
Неактивен
Для каждого А.id из таблицы Б выбираем максимальную дату, результат записывается во временную таблицу t
(select `A.id` id, max(`date`) d from `таблица Б` group by 1) t
Далее объединяем таблицу А с t и Б, чтобы выбрать все поля.
Что касается ошибки, то видимо в таблице Б нет колонки с названием A.id
Неактивен
vasya Большое спасибо за помощь! запрос работает применимо к моим таблицам! Еще вопросик не по теме - знаешь хорошую литературу по MYSql в которой больше практических вопросов, чем теории, так скажем "практикум" ?
Неактивен
http://sqlinfo.ru/forum/viewtopic.php?id=4458
4. Bill Karwin, SQL Antipatterns
Неактивен
vasya написал:
http://sqlinfo.ru/forum/viewtopic.php?id=4458
4. Bill Karwin, SQL Antipatterns
спасибо!
Неактивен
В продолжение темы - интегрировал данное решение применимо к моим таблицам. Отображаю эти 2 таблицы в html виде, где сортировка идет при нажатии на столбец таблицы через ajax. При сортировке к запросу добавляется ORDER BY с названием столбца по которому сортируем в виде имяТаблицы.имяСтолбца ... при этом запрос просто зависает. Я взял 2 запроса с сортировкой вывел на экран, скопировал и запустил по очереди через phpmyadmin - второй запрос завис. Может ли это быть как-то связано с использованием временной таблицы для связи? либо возможно есть еще какие-то причины?
Отредактированно blessed_man (14.10.2011 11:39:31)
Неактивен
Покажите запрос который зависает, его explain и структуру таблиц (show create table `имя таблицы`)
Неактивен
У меня в БД больше 10 000 записей клиентов - одна таблица, каждому из которых может соответствовать до нескольких десятков записей из второй таблицы. Когда я применяю ваш пример к нескольким записям то работает быстро. Если делаю для всех записей, то обрабатывается около 23 секунд, а если ставлю ORDER BY то запрос вообще виснет.
Таблицы там с большим количеством полей, поэтому привожу часть
1-я
Неактивен
vasya написал:
Во-первых, зачем в данном запросе нужен второй left join ?
Во-вторых, нужно добавить индексы, см FAQ №5
Делал по вашему примеру, у вас вверху их тоже 2 штуки )) И ниже ваше же вполне логичное объяснение
Неактивен
Ну так я ориентировался на пример из первого поста, а в вашей окончательной редакции второй join не нужен.
Неактивен
Объясните тогда пожалуйста смысл второго join потому что я думал что он и нужен чтобы объединить таблицы по максимальной дате.
Возможно ли написать мой запрос таким образом чтобы в верху шло перечисление полей с учетом разных таблиц а именно чтобы в названиях полей присутствовали crm_contragents.* и crm_history.*
Отредактированно blessed_man (18.10.2011 13:44:57)
Неактивен
blessed_man написал:
Объясните тогда пожалуйста смысл второго join потому что я думал что он и нужен чтобы объединить таблицы по максимальной дате.
В примере из первого поста вы выбирали данные из второй таблицы (surname ) для получения которых нужно джойнить таблицу по максимальной дате и A.id
В последнем примере вы не выбираете никаких данных из второй таблицы, кроме max(creation_date), которую получаете из подзапроса.
blessed_man написал:
Возможно ли написать мой запрос таким образом чтобы в верху шло перечисление полей с учетом разных таблиц а именно чтобы в названиях полей присутствовали crm_contragents.* и crm_history.*
Ну так и перечислите нужные вам поля.
Писать * плохая практика, лучше явно указывать нужные вам поля.
Неактивен
Спасибо за ваши комменты! но мне второй JOIN нужен так как в выбираемые поля формируются скриптом и возможно там появятся поля из второй таблицы. В принципе можно прописать условие когда добавлять эти JOIN а когда нет в зависимости от того какие поля выбираются... Но это не принципиально... Принципиальна сейчас скорость выполнения запроса она растет в зависимости от количества выбираемых записей - при выборке 50 записей составляет около 24 секунд , и увеличивается - при 100 уже 48 сек.... Возможно сам запрос можно переписать подругому? С ключами пока разбираюсь, понимаю что они существенно увеличивают скорость выполнения запроса, но пока не совсем ясно как этот принцип применить, впервые сталкиваюсь
Неактивен
Попробовал проиндексировать(насколько понимаю), правильно ли я все сделал, посмотрите?
хотелось бы на начальном этапе понимания индексирования получить контроль с вашей стороны, заранее благодарю!
CREATE INDEX index_creation_date ON crm_history (creation_date);
Запрос выполняется в разы быстрее, виснущий запрос выполняется за 8 сек,
возможно можно еще какие-то добавить индексы для быстроты?
Неактивен
blessed_man написал:
В принципе можно прописать условие когда добавлять эти JOIN а когда нет в зависимости от того какие поля выбираются... Но это не принципиально... Принципиальна сейчас скорость выполнения запроса
А она (скорость) зависит от того делаете вы лишний join или нет.
Представте - вам нужно выбрать из корзины зеленые яблоки без черенка. Но вместо того, чтобы перебрать яблоки, отделив нужные, вы сначала для каждого яблока выбираете из ящика с грушами соответствующие ему по цвету и наличию/отсутствую черенка груши, выкладывая это кучками на полу. И только потом отбираете нужные вам яблоки.
Неактивен
blessed_man написал:
Попробовал проиндексировать(насколько понимаю), правильно ли я все сделал, посмотрите?
хотелось бы на начальном этапе понимания индексирования получить контроль с вашей стороны, заранее благодарю!
CREATE INDEX index_creation_date ON crm_history (creation_date);
Запрос выполняется в разы быстрее, виснущий запрос выполняется за 8 сек,
возможно можно еще какие-то добавить индексы для быстроты?
FAQ №5 смотрели?
Для запроса из поста №14 попробуйте
(is_hidden,source_info,date_nextstage)
Вместо созданного вами лучше (contragent_id,creation_date)
Неактивен
Страниц: 1