如果值在连续的时间段内发生,则SQL需要应用可变速率

时间:2016-01-13 18:10:52

标签: sql sql-server-2012 common-table-expression

我有一个看起来像这样的表:

在查询中,我需要找到两个时间段(行)上发生的最大导入值,其中值大于定义的阈值并应用速率。如果它发生超过两个时间段,将使用不同的速率

    WITH CTE AS (  

SELECT LogTable.[LocalTimestamp] as thetime,LogTable.[SystemImport] as import, LogTable.[Id] - ROW_NUMBER() OVER (ORDER BY LogTable.[Id]) AS grp
  FROM {System_KWLogRaw} LogTable
  WHERE LogTable.[SystemImport] between @DemandThreshold and @In1 and 
    DATEPART(year,@inDate) = DATEPART(year, LogTable.[LocalTimestamp]) and
    DATEPART(month,@inDate) = DATEPART(month, LogTable.[LocalTimestamp]) and
    DATEPART(day,@inDate) = DATEPART(day, LogTable.[LocalTimestamp])
),

counted AS (
    SELECT *, COUNT(*) OVER (PARTITION BY grp) AS cnt
    FROM CTE

    )

SELECT MAX(counted.import) as again1
FROM counted
WHERE cnt > 3 and counted.import < (SELECT MAX(counted.import) FROM counted)

Ids 2和3>阈值,因此查询应返回那些(2500,1900)= 1900减去阈值(1000)= 900的MIN值。应用率Rate1 * 900 = 9000

如果我们将Id 4的值更改为1200,则MIN值将为1200.减去阈值= 200. 200 * Rate2 = 4000

非常感谢任何帮助!

反馈后更新。我的挑战似乎是我没有抓住第二高的价值。以下是数据集的示例: Dataset example

我添加了另一个var来缩小列表以测试间隙和岛屿部分。这是一个较小的子集: Subset

以下是代码:

{{1}}

这将返回3555.53而不是3543.2,这是第二高的值

1 个答案:

答案 0 :(得分:0)

这将满足您的要求:

with x as (
select
t1.Id,
t1.DateTime,
t1.Import,
t1.Export,
t1.Total,
count(t2.Import) over (partition by 1) as [QualifyingImports],
min(t2.Import) over (partition by 1) as [MinQualifyingImport]

from
myTable t1
left join myTable t2 on t2.Import > 1000 and t2.Id = t1.Id

where
t1.DateTime >= '2016-01-13'
and t1.DateTime < dateadd(d, 1,'2016-01-13')

)

select
x.Id,
x.DateTime,
x.Import,
x.Export,
x.Total,
case when x.[QualifyingImports] > 2 then (x.MinQualifyingImport - 1000) * 200 else (x.MinQualifyingImport - 1000) * 100 end as [Rate]
from x

我已经整理了一个Fiddle,因此你可以为Id#4使用不同的值。

我真的想把阈值和句点之类的值设置为@variables,但它似乎不支持CTE,所以我只需要对它们进行硬编码。

修改

原来CTE太过分了,你可以把它缩小到这个并使用@variables,耶!

declare @period smalldatetime = '2016-01-13'
declare @threshold float = 1000
declare @rate1 float = 100
declare @rate2 float = 200

select
t1.Id,
t1.DateTime,
t1.Import,
t1.Export,
t1.Total,
case
  when count(t2.Import) over (partition by 1) > 2 then (min(t2.Import) over (partition by 1) - @threshold) * @rate2
  else (min(t2.Import) over (partition by 1) - @threshold) * @rate1
  end as [Rate]

from
myTable t1
left join myTable t2 on t2.Import > @threshold and t2.Id = t1.Id

where
t1.DateTime >= @period
and t1.DateTime < dateadd(d, 1, @period)

Fiddle