Сложное соединение - с учетом диапазонов дат и суммы
Вопрос
У меня есть две таблицы, которые мне нужно присоединиться ... Я хочу присоединиться к Table1 и Table2 на «ID» - однако в таблице два идентификатора не является уникальным. Я хочу, чтобы только одно значение возвращалось для таблицы второй, и это значение представляет собой сумму столбца под названием «total_sold» - в пределах указанного диапазона дат (скажем, один месяц), однако я хочу одновременно более одного диапазона дат ...
SELECT ta.id, sum(tb.total_sold) as total_sold_this_week, sum(tc.total_sold) as total_sold_this_month
FROM table_a as ta
LEFT JOIN table_b as tb ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 WEEK) AND NOW()
LEFT JOIN table_b as tc ON ta.id=tc.id AND tc.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id
Это работает, но не подводит итог рядов - возвращая только одну строку для каждого идентификатора ... Как получить сумму из таблицы B вместо только одной строки ??? Пожалуйста, критикуйте, может ли формат вопроса использовать больше работы - я могу переписать и предоставить образцы данных, если это необходимо - это тривиальная версия гораздо большей проблемы.
-Спасибо
Решение
Использование подборов
Одним из способов решить это было бы использовать подростки. LEFT JOIN
Создает новый «результат» для каждого матча в правой таблице, поэтому использование двух левых соединений создает больше строк, чем вы хотите. Вы можете просто выбрать значение, которое вы хотите, но это может быть медленным:
SELECT ta.id,
(SELECT SUM(total_sold) as total_sold
FROM table_b
WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 WEEK) AND NOW()
AND id=ta.id) as total_sold_this_week,
(SELECT SUM(total_sold) as total_sold
FROM table_b
WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 MONTH) AND NOW()
AND id = ta.id) as total_sold_this_month
FROM table_a ta;
Результат:
+----+----------------------+-----------------------+ | id | total_sold_this_week | total_sold_this_month | +----+----------------------+-----------------------+ | 1 | 3 | 7 | | 2 | 4 | 4 | | 3 | NULL | NULL | +----+----------------------+-----------------------+ 3 rows in set (0.04 sec)
Использование суммы (дело ...)
Этот метод не использует подводы (и, вероятно, будет быстрее в более крупных наборах данных). Мы хотим объединить Table_A и Table_B вместе, используя наш «самый большой диапазон дат, а затем использовать SUM()
на основе CASE
Рассчитать «меньший диапазон».
SELECT ta.*,
SUM(total_sold) as total_sold_last_month,
SUM(CASE
WHEN date_sold BETWEEN NOW() - INTERVAL 1 WEEK AND NOW()
THEN total_sold
ELSE 0
END) as total_sold_last_week
FROM table_a AS ta
LEFT JOIN table_b AS tb
ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id;
Это возвращает почти тот же набор результатов, что и пример подзадна:
+----+-----------------------+----------------------+ | id | total_sold_last_month | total_sold_last_week | +----+-----------------------+----------------------+ | 1 | 7 | 3 | | 2 | 4 | 4 | | 3 | NULL | 0 | +----+-----------------------+----------------------+ 3 rows in set (0.00 sec)
Единственная разница - это 0
вместо NULL
. Анкет Вы можете суммировать столько же датчиков, сколько хотелось бы использовать этот метод, но, вероятно, все еще лучше ограничить ряды, возвращаемые в самый большой диапазон в ON
пункт.
Просто чтобы показать, как это работает: удаление GROUP BY
и SUM()
вызовы и добавление date_sold
На выбор возвращает это:
+----+------------+-----------------------+----------------------+ | id | date_sold | total_sold_last_month | total_sold_last_week | +----+------------+-----------------------+----------------------+ | 1 | 2010-04-30 | 2 | 2 | | 1 | 2010-04-24 | 2 | 0 | | 1 | 2010-04-24 | 2 | 0 | | 1 | 2010-05-03 | 1 | 1 | | 2 | 2010-05-03 | 4 | 4 | | 3 | NULL | NULL | 0 | +----+------------+-----------------------+----------------------+ 6 rows in set (0.00 sec)
Теперь, когда ты GROUP BY id
, и SUM()
Два столбца Total_sold, у вас есть свои результаты!
Старый совет
Прежде чем принести два разных диапазона даты в микс, вы можете использовать GROUP BY
группировать использование идентификатора таблицы в таблице 1 и SUM()
Совокупная функция, чтобы добавить возвращенные ряды.
SELECT ta.id, SUM(tb.total_sold) as total_sold_this_week
FROM table_a as ta
LEFT JOIN table_b as tb
ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -3 WEEK) AND NOW()
GROUP BY ta.id
+----+----------------------+ | id | total_sold_this_week | +----+----------------------+ | 1 | 7 | | 2 | 4 | | 3 | NULL | +----+----------------------+ 3 rows in set (0.00 sec)
Данные тестирования
NOW()
2010-05-03
mysql> select * from table_a; select * from table_b; +----+ | id | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set (0.00 sec) +----+------------+------------+ | id | date_sold | total_sold | +----+------------+------------+ | 1 | 2010-04-24 | 2 | | 1 | 2010-04-24 | 2 | | 1 | 2010-04-30 | 2 | | 1 | 2010-05-03 | 1 | | 2 | 2010-05-03 | 4 | +----+------------+------------+ 5 rows in set (0.00 sec)