Суммировать значения, если они находятся между диапазоном дат sql

#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. Спасибо за помощь!