/ / Zastosuj substracton dla każdego miesiąca - sql, sql-server, sql-server-2012

Zastosuj substracton dla każdego miesiąca - sql, sql-server, sql-server-2012

Mam taki serwer Historian Wonderwareprzechwytuje dane. Muszę zapytać o to za pomocą SQL, aby znaleźć różnicę między ostatnią wartością miesiąca a pierwszą wartością miesiąca (wartość stale rośnie).

Aby wybrać moje dane, zrobiłem to:

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";

Przypuszczam, że będę musiał użyć group i order by, ale na razie utknąłem na tym, że otrzymam ostatnią i pierwszą wartość miesiąca, aby ją odjąć.

Czy znasz sposób zastosowania zapytania?

EDYTOWAĆ

Właściwie chcę wykonywać statystyki, tworząc awykres z "Miesięczne zużycie" (gazu, energii elektrycznej, wody ...). Indeks stale rośnie, więc potrzebuję, dla każdego miesiąca, odejmować pierwszą wartość od ostatniej wartości.

Na przykład, zakładając, że mam tego rodzaju dane:

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

Wynik dla miesiąca maja 2017 musi wynosić 104-12 ==> 92 Wynik miesiąca czerwca 2017 musi wynosić 211-104 ==> 107

A następnie będzie to wyświetlane na wykresie słupkowym.

Odpowiedzi:

4 dla odpowiedzi № 1

Posługiwać się FIRST_VALUE funkcja okna

;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 podejście do starszych wersji

;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

1 dla odpowiedzi nr 2

Jeśli wartości stale rosną, znacznie łatwiej jest pracować z minimalnymi i maksymalnymi wartościami każdego miesiąca zamiast z pierwszego i ostatniego (powinny być one zgodne z rzeczywistością).

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)

0 dla odpowiedzi № 3

To wybierze wartość z twojej tabeli, gdzie DateTime pole znajduje się w bieżącym miesiącu. Czy to jest to, czego chcesz?

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

0 dla odpowiedzi nr 4

Możesz użyć SQL takiego jak ten

 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