Объединение таблиц с различными измерениями данных (еженедельно и ежедневно)

У меня есть таблица с еженедельным сбором данных и вторая таблица с ежедневным сбором данных. Мне нужно сделать объединение между таблицами (INNER JOIN) через ключ id и для ежедневных значений таблицы, агрегировать их в среднем за неделю.

Итак, моя результирующая таблица также будет с недельными датами, и для каждой недели она должна представлять среднее значение id за предыдущие 7 дней (включая день приобретения).

Образцы данных: DBfiddle

В этом примере операции соединения и группировки возвращают правильные результаты. Но он берет глобальное среднее значение, а не среднее значение, соответствующее предыдущим 7 дням для каждой еженедельной даты приобретения.

Кто-нибудь знает, как лучше всего это решить?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Подзапроса будет достаточно, но только если вас интересуют именно последние 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среднее
1102022-04-185
18.22022-04-2514.57142

В прикрепленном примере вы также указываете значения времени (но из-за определения таблицы они обрезаются во время вставки)

Ваш ответ мне очень помог, но при применении запроса непосредственно к моей базе данных я сталкиваюсь с проблемой: подзапрос использует несгруппированный столбец "a1.aquisition_date из внешнего запроса. Я нашел что-то связанное с Прекратить ссылаться на несгруппированные столбцы из внешнего запроса в подзапросе. Есть ли способ изменить запрос, чтобы избежать этого ошибка? (Помня, что в моем запросе есть группы, которые я передал в DBfiddle, не освещенные в вашем ответе.) Кроме того, в DBfiddle запрос работает, а в реальной БД - нет.

Tridapalli_26 06.05.2022 15:31

В порядке. Я проверю группы в исходном запросе

Kadet 06.05.2022 15:36
DBfiddle. Даже зная, что запрос отлично работает в DBfiddle, было бы здорово, если бы был способ изменить его для этих требований использования внешних агрегированных результатов в подзапросах. Любое предложение будет полезно.
Tridapalli_26 06.05.2022 15:40

Вам больше не нужно внутреннее соединение с table2 и GROUPING INNER JOIN table2 table2 ON table2.id = table1.id GROUP BY table1.id ,table1.rating ,DATE(table1.aquisition_date)

Kadet 06.05.2022 15:45

Если вы хотите сохранить группировку (поскольку запрос создается где-то еще или больше, чем в примере), вы можете сохранить группу по разделам. Доставьте запрос, который вызывает ошибку "подзапрос использует несгруппированный столбец "a1.aquisition_date из внешнего запроса"

Kadet 06.05.2022 15:47

Краткий ответ: Вы должны включить неделю в 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 05.05.2022 22:52

@shawnt00 Верно!

nCessity 05.05.2022 22:54

Другие вопросы по теме