问题
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