У меня есть таблица с еженедельным сбором данных и вторая таблица с ежедневным сбором данных. Мне нужно сделать объединение между таблицами (INNER JOIN) через ключ id и для ежедневных значений таблицы, агрегировать их в среднем за неделю.
Итак, моя результирующая таблица также будет с недельными датами, и для каждой недели она должна представлять среднее значение id за предыдущие 7 дней (включая день приобретения).
Образцы данных: DBfiddle
В этом примере операции соединения и группировки возвращают правильные результаты. Но он берет глобальное среднее значение, а не среднее значение, соответствующее предыдущим 7 дням для каждой еженедельной даты приобретения.
Кто-нибудь знает, как лучше всего это решить?
Подзапроса будет достаточно, но только если вас интересуют именно последние 7 дней для каждой строки
select id, rating, aquisition_date ,
(select avg(value) from table2 a2 where a2.id = a1.id and
a2.aquisition_date between a1.aquisition_date - 6 and a1.aquisition_date) avg
from table1 a1
Полученные результаты
я бы | рейтинг | aquisition_date | среднее |
---|---|---|---|
1 | 10 | 2022-04-18 | 5 |
1 | 8.2 | 2022-04-25 | 14.57142 |
В прикрепленном примере вы также указываете значения времени (но из-за определения таблицы они обрезаются во время вставки)
В порядке. Я проверю группы в исходном запросе
Вам больше не нужно внутреннее соединение с table2 и GROUPING INNER JOIN table2 table2 ON table2.id = table1.id GROUP BY table1.id ,table1.rating ,DATE(table1.aquisition_date)
Если вы хотите сохранить группировку (поскольку запрос создается где-то еще или больше, чем в примере), вы можете сохранить группу по разделам. Доставьте запрос, который вызывает ошибку "подзапрос использует несгруппированный столбец "a1.aquisition_date из внешнего запроса"
Краткий ответ:
Вы должны включить неделю в JOIN
:
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week
,table1.rating AS table1_rating
,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id AND
EXTRACT(WEEK FROM table1.aquisition_date) = EXTRACT(WEEK FROM table2.aquisition_date)
GROUP BY
table1.id
,table1.rating
,table1.aquisition_date
;
Это дает нам
id week table1_rating table2_value_avg
1 17 8.2 20.0000000000000000
1 16 10 13.1428571428571429
Длинный ответ: Как нам туда добраться? Рассмотрим внутреннее соединение без как агрегацию:
Ваша первая попытка
SELECT
table1.id
,EXTRACT(WEEK FROM table1.aquisition_date) AS week1
,EXTRACT(WEEK FROM table2.aquisition_date) AS week2
-- ,AVG(EXTRACT(WEEK FROM table2.aquisition_date)) AS week2
,table1.rating AS table1_rating
,table2.value AS table2_value
-- ,AVG(table2.value) as table2_value_avg
FROM
table1 table1
INNER JOIN
table2 table2
ON
table2.id = table1.id
Это сопоставит строки из обеих таблиц, которые не принадлежат друг другу, например, значения за 15-ю неделю с рейтингами за 16-ю неделю.
id week1 week2 table1_rating table2_value
1 16 15 10 2
1 16 15 10 4
[... 40 more rows]
На самом деле он соответствует каждой строке из таблицы 1 с таблицей 2. Вот почему среднее значение является мировым средним, даже если GROUP BY
работает.
Таким образом, решение, приведенное выше, заключается в удалении тех строк из внутреннего соединения, где недели не совпадают.
N.B.: Если вы хотите включить данные в свои результаты, где данные есть только в одной из таблиц, вам нужен FULL OUTER JOIN
, но идея та же.
NB: (Спасибо, @shawnt00) (ДОПОЛНИТЕЛЬНАЯ НЕДЕЛЯ ОТ ...) означает ISO 8601 неделя. Она начинается в понедельник, и могут быть другие определения недели.
NB: (Спасибо @shawnt00) В решении год не учитывается. Если присутствуют данные более чем за один год, вам необходимо сопоставить год и неделю в JOIN.
Обратите внимание, что номер недели ISO может не соответствовать определению недели OP. И если даты охватывают более года, вам также необходимо включить это.
@shawnt00 Верно!
Ваш ответ мне очень помог, но при применении запроса непосредственно к моей базе данных я сталкиваюсь с проблемой: подзапрос использует несгруппированный столбец "a1.aquisition_date из внешнего запроса. Я нашел что-то связанное с Прекратить ссылаться на несгруппированные столбцы из внешнего запроса в подзапросе. Есть ли способ изменить запрос, чтобы избежать этого ошибка? (Помня, что в моем запросе есть группы, которые я передал в DBfiddle, не освещенные в вашем ответе.) Кроме того, в DBfiddle запрос работает, а в реальной БД - нет.