#sql-server
#sql-сервер
Вопрос:
Я хочу суммировать значения, где дата находится между датой создания и конечной датой, следовательно, ValueEnd .
Для экземпляров второй строки дата создания совпадает с конечной датой, поэтому я должен суммировать ValuePerDay этого дня с предыдущим значением. Итак, в столбце ValueEnd это 3,4 1,17 = 4,57
Я начал с вычисления суммы за те дни, когда разница равна 1, вот так:
SELECT
CONVERT(CHAR(10), CreationDate,103) CreationDate
,CONVERT(CHAR(10), EndDate,103) EndDate
,SUM(Values_an) Values_an
FROM Dat1
WHERE Difference=1
GROUP BY CONVERT(CHAR(10), CreationDate,103), CONVERT(CHAR(10), EndDate,103), Difference
Однако у меня возникают проблемы с суммированием значений, где разница больше 1. Может кто-нибудь мне помочь, пожалуйста?
Комментарии:
1. «У меня проблемы» — это не описание проблемы. Что происходит, когда вы пытаетесь это сделать? Почему это неправильно?
2. Это не имеет смысла, если значение первых строк для
ValueEnd
равно 4,63 (3,5 1,13), почему значение 2-й строки не 6.89 ((1.13 * 3) 3.5)? Откуда вообще берется 3.5?3. На самом деле это так, потому что, если разница между конечной датой и датой создания равна 1, то значение должно быть одинаковым имеет Values_an
4. @Sofia тогда почему (в первой строке) value_an 3.4 и ValuePerD 3.5? И откуда ваш 1.13? Значение в день равно 3,5, поэтому оно должно быть Difference * ValuePerD, нет?
5. @Tyron78 вы правы. Я допустил ошибку при сборе данных. Теперь это то же самое
Ответ №1:
Хорошо, судя по предоставленной информации — и, насколько я все правильно понял, следующий подход может решить вашу проблему:
DECLARE @t TABLE(
CreationDate date,
EndDate date,
Value_An decimal(19,4)
)
INSERT INTO @t VALUES
('2019-03-01', '2019-03-01', 3.4)
,('2019-03-01', '2019-03-03', 3.5)
,('2019-05-01', '2019-05-01', 3.6)
,('2019-06-01', '2019-06-04', 3.7)
;WITH cteMultiRow AS(
SELECT CreationDate, COUNT(*) cntRows
FROM @t
GROUP BY CreationDate
HAVING COUNT(*) > 1
),
cte AS(
SELECT t.*
,ROW_NUMBER() OVER (PARTITION BY t.CreationDate ORDER BY t.EndDate) AS rn
,DATEDIFF(d, t.CreationDate, t.EndDate) 1 AS Difference
,CASE WHEN m.CreationDate IS NOT NULL THEN t.Value_An/(DATEDIFF(d, t.CreationDate, t.EndDate) 1) ELSE t.Value_An END AS ValuePerD
FROM @t t
LEFT JOIN cteMultiRow m ON t.CreationDate = m.CreationDate
),
cteSums AS(
SELECT c.CreationDate, SUM(c.ValuePerD) AS ValuePerD
FROM cte c
GROUP BY c.CreationDate
)
SELECT c.CreationDate, c.EndDate, c.Value_An, c.Difference, c.ValuePerD, ISNULL(s.ValuePerD, c.Value_An) AS ValueEnd
FROM cte c
LEFT JOIN cteSums s ON c.CreationDate = s.CreationDate AND c.rn = 1
Комментарии:
1. Спасибо за помощь!