![]() |
Модераторы: skyboy |
![]() ![]() ![]() |
|
hollywood |
|
||||||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Здравствуйте!
Уже пару дней воюю с проблемой, пробовал так и эдак, перелопатил кучу инфы, но что-то тяму не хватает. Поможите пожалуйста, люди добрые! ![]() В принципе, суть задачи проста: есть несколько разных таблиц, в которых есть одинаковые поля. Допустим, это таблицы table_1 и table_2. В каждой из них есть поля user_id, quant, cost. user_id - это поле, описывающее, к кому относится запись, quant и cost - конкретные параметры данной записи. Для примера: -------------------- table_1: (user_id|quant|cost) 1 1 2 2 2 4 1 1 1 table_2: (user_id|quant|cost) 3 1 3 2 1 1 3 2 1 users: (id|name) 1 vasya 2 fedya 3 misha -------------------- мне нужно сделать выборку из обоих таблиц (table_1, table_2) с группировкой по id пользователя (но вместо id нужно подставить имя). При этом величины из столбцов quant, cost нужно суммировать. Т.е. результатом выборки должна стать таблица: vasya 2 3 fedya 3 5 misha 3 4 т.е. для каждого пользователя считается суммарное значение столбцов quant и суммарное значение столбцов cost из всех таблиц. Помогите пожалуйста грамотно составить MySQL запрос, который это дело реализует. Пробовал сделать что-то вроде:
в самых разнообразных вариациях. Ноль эффекта. У меня уже мозга за мозгу заходит. Добавлено через 6 минут и 15 секунд Мда, кстати, пробовал упростить запрос, чтобы разобраться в проблеме. По полочкам разложить так сказать. Для начала пытался делать без подстановки имени вместо id пользователя и суммирование делал только по одной таблице:
тут все нормально. но как только попробовал сделать выборку из 2х таблиц сразу:
Сразу же результаты суммирования чуть не на порядок возрастают. Просто невообразимые числа откуда-то берутся. Почему так получается? |
||||||
|
|||||||
Deniz |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 6 Всего: 44 |
А вот так:
но если хоть одно quant или cost буде null, получишь null в соотв. столбце. Это сообщение отредактировал(а) Deniz - 4.5.2008, 06:27 -------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
Я бы решал подзапросами или вьювами. Особенно с учетом того что user_id в таблицах данных имеет место повторяться:
1) суммирование quant и cost по первой таблице с группировкой по user_id 2) то же, но по второй 3) left join полученных запросов в таблицу юзеров и суммирование с использованием проверок на null и замены таковых на нули (не помню функцию мускула) По крайней мере это получится читаемо, и видна логика. Первые 2 запроса лучше оформить вьювами - будет чуть быстрее, чем собирать все в одного большого крокодила. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Большое спасибо за советы, прямо сейчас и попробую еще повоевать
![]() 2 небольших уточнения: 1) не совсем понял, что такое вьювы, а так же что за подзапросы? Насколько я знаю, мускул вложенных запросов ведь не поддерживает... 2) я работаю в связке php+mysql. разве можно одним вызовом mysql_query() сделать последовательно несколько связанных запросов? если я правильно понял логику, можно сперва сделать два запроса, объединенных в union с выборками сумм столбцов для каждой таблицы, а потом выборку с суммированием еще по этой итоговой таблице? С 3-м шагом вроде понятно... |
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
Предлагаете поверить, что ? А вообще начинать надо с озвучивания версий. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Если быть честным, недавно перешел на связку php 5.2.4 + mysql 5.0.45. До этого работал с более старыми версиями. Вложенные запросы в мускуле появились с 4 версии, если верить тому, что я читал. Поэтому я не хотел их использовать, т.к. еще не совсем ясно, на каком хостинге будет работать скрипт.
"куча инфы" понятие относительное. Будем говорить так: речь идет об объеме информации, касающейся выборки из нескольких таблиц, найденной через поисковики за 3 дня. Форумы, мануалы и т.д. К сожалению, решить задачу самостоятельно, основываясь на полученной информации, мне не удалось. Честно говоря, в том, что касается языка SQL - я новичек. Так что, если не в лом, дайте пожалуйста пример, как должны выглядеть запросы, согласно Вашей схеме. |
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
Вот как это выглядит в Аксессе (без обработки)
-------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Попробовал сделать как Вы предложили. Конечные суммы вообще заоблачные получаются, совершенно неправдоподобные. Вот что высянилось из "ковыряний": я попробовал убрать группировку и вместо сумм в SELECT поставил "*", чтобы глянуть на конечную таблицу, из которой происходит выборка. Как говорится, "Атилла в недоумении": таблицы-то он сращивает, но при этом почему-то так получается, что в той таблице, в которой было больше записей, они удваиваются (т.е. каждой записи становистя вдвое больше), а в той, в которой меньше - просто чередуются. У кого-нибудь есть ссылка на человечьий учебник или справочник, в котором есть описание команды JOIN? Меня уже достало это разтиражированное по всему инету руководство с php.ru, из которого про JOIN хрен что поймешь. |
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
http://downloads.mysql.com/docs/refman-4.0-ru.html.zip пункт 6.4.1.1. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Спасибо огромное! Все работает! ![]() ![]() Кой-чего чего маленько переделал с учетом специфики структуры БД и данных, и вот, что получилось:
Оп-ля! ![]() Это сообщение отредактировал(а) hollywood - 5.5.2008, 11:19 |
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
Трудно сказать "с учетом специфики структуры БД", но скобки вокруг поля в Group By могут превратить поле в выражение и привести к не-использованию индеса. Это не арифметика, и избыток скобок может быть так же вреден, как и недостаток. -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
||||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
А тогда зачем проверять оба? -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
||||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Один неожиданный (по крайней мере, для меня) момент. Столбцы cost в моих таблицах - float(5,2). При попытке упорядочить "ORDER BY cost" (упорядочиваю самый "верхний" запрос в варианте с UNION'ами) наблюдается презабавнейшая катавасия. Упорядочивается это дело как угодно, но только не по цене. Это из-за "GROUP BY user_id" такое веселье получается?
Добавлено через 4 минуты и 48 секунд ![]()
|
|||
|
||||
Akina |
|
|||
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 45 Всего: 454 |
Сортировка в подзапросе не имеет смысла.
-------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
hollywood |
|
||||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
История продолжается... Итак, ценой неимоверных умственных усилий мы получили-таки табличку:
vasya 2 3 fedya 3 5 misha 3 4 ![]() теперь сверхзадача заключается в том, чтобы к оной табличке в конец добавить строчку со сводным суммированием, т.е. нужна таблица: vasya 2 3 fedya 3 5 misha 3 4 total 8 12 для получения изначальной таблицы использовал вариант с UNION-ами:
попробовал решить текущую задачу таким макаром:
Мускул справедливо вопрошает, чего я покурил и откуда взял Total во втором запросе верхнего (по уровню вложения) UNION-а. Понять я его, конечно могу ![]() ![]() Можно как-нибудь задать глобальную пользовательскую переменную с таблицей Total? С тем, чтобы результаты можно было использовать и в других SELECT-ах. Или как это лучше сделать? Это сообщение отредактировал(а) hollywood - 9.5.2008, 12:55 |
||||
|
|||||
skyboy |
|
|||
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 15 Всего: 260 |
создать временную(TEMPORARY) таблицу (возможно, будет ещё быстрее, если создать в памяти(ENGINE=MEMORY)). заполнить. временная таблица с точки зрения каждого отдельного connection к базе имеет уникальное содержимое. и сможешь в своих запросах до закрытия подключения к БД использовать любое количество раз ![]() |
|||
|
||||
hollywood |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 20.10.2007 Репутация: нет Всего: нет |
Спасибо, вариант интересный. Стоит того, чтобы с ним хотя бы поковыряться. Я вот тут только голову ломаю: может не стоит заморачиваться с запросом, а конечную сумму в скрипте уже посчитать? Это, конечно, уже не так красиво выглядит, но я опасаюсь за быстродействие... По сравнению с реализацией суммирования в php во время итерирования по результатам запроса - создание временной таблицы в памяти сильно медленнее должно быть?..
|
|||
|
||||
Fortop |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2200 Регистрация: 13.11.2007 Где: Донецк Репутация: 2 Всего: 42 |
hollywood,
Если у тебя 3 строки в итоговом запросе - то где хочешь, там и суммируй. Ты еще не знаешь своих узких мест, а уже пытаешься оптимизировать. Сделай два запроса и не мучайся. Вот когда наступит время оптимизации, тогда и будешь думать, выбирать ли во временную таблицу или посчитать в скрипте. -------------------- Мир это Я. Живее всех живых. |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Составление SQL-запросов | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |