Мне удалось решить этот MySQL-Riddle, и я думаю, что пока не ясно.
У меня есть таблица со следующей структурой (то есть):
ID | Date | Attr1 | Attr2
1 | 2018-01-31 12:00:00 | 5 | 7
2 | 2018-01-31 12:10:00 | 4 | 3
3 | 2018-01-31 12:20:00 | 0 | 7
...
...
k | 2018-02-01 00:00:00 | 4 | 5
k+1| 2018-02-01 00:10:00 | 1 | 3
...
и так далее...
Я пытаюсь вычислить SUM (Attr1) как S1, SUM (Attr2) как S2 и разницу между этими значениями (S1-S2). Я достиг этого, используя "Self-Inner Join" (как описано здесь).
Проблема, которую я еще не решил: я получаю всю (целую) СУММУ значений, и я хочу сбросить эти S1 и S2 при изменении дня. У меня есть записи в течение нескольких месяцев, и я делаю это вручную, это не будет хорошим выбором для меня.
Есть ли у вас какие-либо рекомендации? Я благодарен за ваши сообщения и помощь. Мой уровень SQL - это Beginner-Intermediate, и я не помню, как это сделать.
Спасибо большое за вашу помощь.
РЕДАКТИРОВАТЬ:
Мой ожидаемый результат
ID | Date | Attr1 | Attr2 | S1 | s2 | S1 -S2
1 | 2018-01-31 12:00:00 | 5 | 7 | 5 | 7 | -2
2 | 2018-01-31 12:10:00 | 4 | 3 | 9 | 10 | -1
3 | 2018-01-31 12:20:00 | 0 | 7 | 9 | 17 | -8
...
...
k | 2018-02-01 00:00:00 | 4 | 5 | 4 | 5 | -1
k+1| 2018-02-01 00:10:00 | 1 | 3 | 5 | 8 | -3
...
EDIT 2: я разделяю то, что я пытался сделать не следующим:
select t1.id, t1.date, t1.attr1, t1.attr2,
t2.id, t2.date, t2.attr1, t2.attr2,
sum(t2.attr1) as cumAttr1,
sum(t2.attr2) as cumAttr2,
sum(t2.attr1) - sum(t2.attr2) as diffAttrs
from table t1
inner join table t2
on t1.date >= t2.date
group by t1.id, t1.attr1
order by t1.date
С этим я получу всю группу строк с ее суммой, но каждый день я бы хотел сбросить значение "сумма".
Еще раз, я ценю ваши отзывы.
EDIT 2:
Я понял, можно получить те же результаты с сохраненными процедурами и немного больше порядка на моей стороне (facepalm). Это * не * необходимо, чтобы выполнить все с помощью одного SELECT
С наилучшими пожеланиями, все. Спасибо за все!
Это то, что вы хотите?
select date(date), sum(attr1), sum(attr2),
sum(attr1) - sum(attr2) as diff
from t
group by date(date);
Я не вижу, что самосоединение связано с этой проблемой.
РЕДАКТИРОВАТЬ:
Кажется, вы хотите получить кумулятивную сумму. Я бы подошел к этому для общей проблемы:
select t.*,
(select sum(tt1.attr1)
from t tt1
where tt1.date <= t.date
) as running_attr1,
(select sum(tt2.attr2)
from t tt2
where tt2.date <= t.date
) as running_attr2
from t;
Чтобы перезапустить каждый день, вы просто добавляете к предложению where
:
select t.*,
(select sum(tt1.attr1)
from t tt1
where date(tt1.date) = date(t.date) and tt1.date <= t.date
) as running_attr1,
(select sum(tt2.attr2)
from t tt2
where date(tt2.date) = date(t.date) and tt2.date <= t.date
) as running_attr2
from t;
Не видя своего первоначального запроса, я не могу быть уверен, насколько вы были близки; но это должен быть самый простой запрос на объединение, чтобы получить указанные вами результаты.
SELECT t.ID, t.Date, t.Attr1, t.Attr2
, SUM(tPrev.Attr1) AS S1, SUM(tPrev.Attr2) AS S2
, SUM(tPrev.Attr1)-SUM(tPrev.Attr2) AS 'S1 -S2'
FROM t AS t
LEFT JOIN t AS tPrev
ON DATE(t.Date) = DATE(tPrev.Date) -- Get records from the day of t
AND tPrev.Date <= t.Date -- But only ones earlier in the day, or t itself
GROUP BY t.ID, t.Date, t.Attr1, t.Attr2
;