Apply a substracton for each month

穿精又带淫゛_ 提交于 2019-12-13 07:24:17

问题


I have a Wonderware Historian server that captures data. I have to query it with SQL to find difference between the last value of a month and the first value of a month (the value is constantly growing).

To select my data, I did this :

SELECT Annees=YEAR(DateTime),Mois=MONTH(DateTime),Value=()
FROM AnalogHistory where TagName = 'OBJECT_TAG_NAME'
AND DateTime >= '01/01/2016 00:00:00' 
AND DateTime <= '24/07/2017 13:53:31';

I supposed I will need to use group and order by, but for now, I'm stuck on how I will get the last and the first value of a month, to subtract it.

Do you know a way to apply the query ?

EDIT

Actually, I want to perform stats by creating a chart with the "Monthly consumption" (of gas, electricity, water...). The index is constantly growing so I need, for each month, to subtract the first value from the last value.

For example, supposing I have this kind of data :

Date                | Index
------              | ------
2017-05-01 00:00:00 | 12
2017-05-01 03:57:00 | 14
2017-05-29 15:00:00 | 97
2017-05-31 22:54:00 | 104
2017-06-01 03:54:00 | 107
2017-06-30 21:54:00 | 211

The result for the month of May 2017 must be 104-12 ==> 92 The result for the month of June 2017 must be 211-104 ==> 107

And then, this will be displayed in a bar chart.


回答1:


Use FIRST_VALUE window function

;with cte as
(
SELECT distinct 
   Annees=YEAR(DateTime),
   Mois=MONTH(DateTime),
   firstRecord = first_value(value)over(partition by YEAR(DateTime),MONTH(DateTime) order by DateTime asc),
   lastRecord = first_value(value)over(partition by YEAR(DateTime),MONTH(DateTime) order by DateTime desc)
FROM AnalogHistory 
where TagName = 'OBJECT_TAG_NAME'
AND DateTime >= '01/01/2016 00:00:00' 
AND DateTime <= '24/07/2017 13:53:31'
)
select 
    Annees,
    Mois, 
    value = isnull(lastRecord,0) - isnull(firstRecord ,0)
from cte

Row_Number approach for older versions

;with cte as
(
SELECT 
   Annees=YEAR(DateTime),
   Mois=MONTH(DateTime),
   firstRecord = Row_Number(value)over(partition by YEAR(DateTime),MONTH(DateTime) order by DateTime asc),
   lastRecord = Row_Number(value)over(partition by YEAR(DateTime),MONTH(DateTime) order by DateTime desc)
FROM AnalogHistory 
where TagName = 'OBJECT_TAG_NAME'
AND DateTime >= '01/01/2016 00:00:00' 
AND DateTime <= '24/07/2017 13:53:31'
)
select Annees,Mois,
       min(case when lastRecord = 1 then value end) - 
       min(case when firstRecord = 1 then value end)
From Cte 
Where 1 in (lastRecord,firstRecord )
Group by Annees,Mois



回答2:


If the values are ever growing it is much easier to work with the minimum and maximum values of each month instead of first and last (they should be indentical).

SELECT 
    YEAR(DateTime) AS Annee, MONTH(DateTime) AS Mois,
    MIN(Value) As MinVal, MAX(Value) As MaxVal,
    MAX(Value) - MIN(Value) As Difference,
FROM AnalogHistory 
WHERE
    TagName = 'OBJECT_TAG_NAME' AND
    DateTime >= '01/01/2016 00:00:00' AND
    DateTime <= '24/07/2017 13:53:31'
GROUP BY YEAR(DateTime), MONTH(DateTime)
ORDER BY YEAR(DateTime), MONTH(DateTime)



回答3:


This will select the value from your table where the DateTime field is within the current month. Is this what you want?

SELECT Value, *
FROM AnalogHistory 
WHERE TagName = 'OBJECT_TAG_NAME'
AND YEAR(DatTime) = YEAR(GETDATE())
AND MONTH(DateTime) = MONTH(GETDATE())



回答4:


You can use a SQL like this one

 WITH cte_min_date 
     AS (SELECT Row_number() 
                  OVER ( 
                    partition BY Year([datetime]) * 100 + Month([datetime]) 
                    ORDER BY [datetime]) AS rn, 
                [datetime], 
                [value] 
         FROM   analoghistory 
         WHERE  tagname = 'OBJECT_TAG_NAME' 
                AND datetime >= '01/01/2016 00:00:00' 
                AND datetime <= '24/07/2017 13:53:31'), 
     cte_max_date 
     AS (SELECT Row_number() 
                  OVER ( 
                    partition BY Year([datetime]) * 100 + Month([datetime]) 
                    ORDER BY [datetime] DESC) AS rn, 
                [datetime], 
                [value] 
         FROM   analoghistory 
         WHERE  tagname = 'OBJECT_TAG_NAME' 
                AND datetime >= '01/01/2016 00:00:00' 
                AND datetime <= '24/07/2017 13:53:31') 
SELECT a.[datetime], 
       b.[datetime], 
       Year(a.[datetime]) * 100 + Month(a.[datetime]), 
       b.[value] - a.[value] AS [Value] 
FROM   cte_min_date a 
       INNER JOIN cte_max_date b 
               ON Year(a.[datetime]) * 100 + Month(a.[datetime]) = 
                             Year(b.[datetime]) * 100 + Month(b.[datetime]) 
                  AND a.rn = b.rn 
WHERE  a.rn = 1 


来源:https://stackoverflow.com/questions/45283415/apply-a-substracton-for-each-month

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!