Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. SQL Timeout von 15 sek erhöhen

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    SQL Timeout von 15 sek erhöhen

    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      thomassch last edited by

      Hallo Zusammen,

      ich rufe mit SendTo eine SQL procedure auf, die leider länger als 15 sek benötigt (mehr optimieren kann ich sie auch leider nicht mehr).
      Es sind einfach ca. 1 Mio Datensätze die recherchiert werden.
      Nach 15 sek. wird SendTo aber abgebrochen mit einem TimeOut Fehler.

      Gibt es irgendeine Möglichkeit diese timeout Zeit zu erhöhen oder ist das im Adapter so definiert?

      Die Fehlermeldung dazu ist:
      javascript.0 (30008) script.js.SQL_Abfragen.SQL_DeltaAbfragen: RequestError: Timeout: Request failed to complete in 15000ms

      Der Code im Script ist so:

      function SQLquery() {
          var idQuery = myQueryDelta;
          if (logging>=2) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= '+idQuery,"info");
      
          var xStart = new Date(); // Zeit messen
          sendTo('sql.0', 'query', idQuery, function (result) {
              var xTime = (new Date() - xStart)/1000; // Zeit s messen
              if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"info");
              setState(idTimeResult_Duration,xTime,true);
      
              if (result.error) {
                  log(result.error);
                  log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"error");
              } else {
                  // show result
                  if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"info");
                  if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQueryresultJSON= '+JSON.stringify(result.result),"info");
                  setState(idResultJson,JSON.stringify(result.result),true);
                  setState(idLastResult_CallWithoutError,formatDate(xStart, "TT.MM.JJJJ hh:mm:ss"),true);
              }
          });
      }
      

      Danke für jeden Tipp dazu.,

      Gruss
      Thomas

      F 1 Reply Last reply Reply Quote 0
      • F
        fastfoot @thomassch last edited by

        @thomassch 1Million Datensätze ist ja nicht die Welt für ne DB, evtl. hat es dir die Indexe geschreddert. Bau die mal neu auf, wenn du magst kannst du auch mal die Procedure posten

        T 1 Reply Last reply Reply Quote 0
        • T
          thomassch @fastfoot last edited by

          @fastfoot

          Die Indizies sind neu erstellt, das bringt nicht so viel dass ich in unter die 15 sek komme.

          Die Prozedure verdichtet Daten aus ts_number auf Stundenwerte und speichert diese dann in eine neue Tabelle, wobei ich hier immer nur die letzten 7 Tage anschaue, verdichte und kopiere, damit ich nicht immer 20 Mio Werte mit mehreren Jahren ständig berechnen muss.

          Warum verdichte ich auf Stundenwerte m? Das ist eigentlich einfach, ich zeige Tabellen in der vis an in der ich über Jason eine Anzeige der Tages, Monats und Jahresverbräuche mache. Würde ich da ständig über alle Werte gehen in ts_number, würde es zu lange dauert.

          Ich habe ganz bewusst keine Iobroker Datenpunkte erzeugt die auf Tage basieren, sondern wollte nachträglich meine alten absoluten Zählerstände verwenden können aus ts_number.
          Ich denke das Problem ist dass ich mittlerweile 20 Mio Einträge in ts_number habe und 1 Mio in der Stundentabelle die ich erzeuge, die joins sind dann schon etwas aufwendiger.

          Die procedure kann ich gerne mal posten diese ist aber sehr lang und komplex, daher wollte ich erstmal versuchen die 15 Sekunden zu erhöhen.

          Gruß
          Thomas

          T 1 Reply Last reply Reply Quote 0
          • T
            thomassch @thomassch last edited by

            @thomassch

            Für die die die procedure interessiert

            USE [iobroker]
            GO
            /****** Object:  StoredProcedure [dbo].[usp_CopyNewHoursValuesTable]    Script Date: 22.06.2023 21:52:48 ******/
            SET ANSI_NULLS ON
            GO
            SET QUOTED_IDENTIFIER ON
            GO
            -- =============================================
            -- Author:		Thomas Schatz
            -- Create date: 26.01.2023
            -- Description:	procedure für das Ermitteln der Differenzwerte pro Stunde
            -- =============================================
            -- ein paar sammlungen von guten Abfragen
            -- 		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy') as xYear, 
            		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM') as xMonth, 
            		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd') as xDay, 
            		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd HH') AS xLastDayHour, 
            		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd HH:mm:ss') AS xTimeSec,
            -- =============================================
            -- VERSION
            -- V5.0  ... inklusive löschen der Werte in IOBroker Werte die älter sind als 1 Tag
            -- 
            
            ALTER PROCEDURE [dbo].[usp_CopyNewHoursValuesTable] 
            	-- Add the parameters for the stored procedure here
            	@ClearAll INT = 0, -- 1 == löscht die letzten x-Tage, -1 läöscht dann alle Werte in der Tabell usr_IOBroker_Werte komplett
            	@RunWithoutCopy INT = 1, -- 1== es wird nur angezeigt aber nichts kopiert
            	@Debug int = 0, -- bei 1 werden alle Debugs angezeigt
            	@DebugOnlyObject varchar(100) ='',
            	@MaxDays INT = 1,-- maximale Anzahl der zu kopierenden Werte, damit die Abfragezeit nicht zu gross wird
            	@StartDate datetime = '',
            	@EndDate datetime = ''
            AS
            BEGIN
            	-- SET NOCOUNT ON added to prevent extra result sets from
            	-- interfering with SELECT statements.
            	SET NOCOUNT ON;
            
            	-- sicherstellen das die Procedure nicht 2x läuft (1x IOBeroker Script und einmal hier im SQL Exec)
            	BEGIN TRANSACTION
            
                -- Insert statements for procedure here
            	DECLARE @xStartDate DATETIME, @xStartDateMin DATETIME, @xEndDate DATETIME, @xNewestDate DATETIME, @xNewest_IOWerte DATETIME, @xOldest_tsNumber DATETIME, @xOldest_IOWerte DATETIME;
            	DECLARE @xTempDateTime DATETIME, @xTemp_Datetime DATETIME;
            	DECLARE @xTempBigInt BIGINT;
            	DECLARE @xStartDateUNIX BIGINT, @xEndDateUNIX BIGINT
            	DECLARE @RunTime DATETIME;
            	DECLARE @NewAnzahl as int, @NewAnzahl1 as int;
            	DECLARE @myId as int;
            	DECLARE @bNewest as bigint;
            	DECLARE @OldValuesCount as bigint, @OldValuesCountBeforeDelete as bigint, @NewValuesCount as bigint;
            	Declare @xOldest_ref as bigint;
            	DECLARE @xNewest_IOWerte_AddDays as datetime;
            	DECLARE @CountAnzahl as int, @runtimestart as datetime;
            	DECLARE @CurrentTime as bigint;
            
            	-- wurd ein Filterobject übergeben
            	set @myId=0
            	if (@DebugOnlyObject<>'') 
            	BEGIN
            		Select 'Es wurde ein FilterObject übergeben'
            		select @DebugOnlyObject
            		Select @myId = id from datapoints where name=@DebugOnlyObject
            	END
            
            	-- Tabelle erstellen, falls nicht extiert
            	IF  NOT EXISTS (SELECT * FROM sys.objects 
            	WHERE object_id = OBJECT_ID(N'[dbo].[usr_IOBroker_Werte]') AND type in (N'U'))
            	BEGIN
            		CREATE TABLE dbo.usr_IOBroker_Werte (
            			id int not NULL,
            			create_ts bigInt,
            			UnixTime bigint,
            			min_ts bigint,
            			max_ts bigint,
            			Zaehler real,
            			[DateTime] datetime,
            			Diff real,
            			CONSTRAINT IOBroker_WerteIndex UNIQUE  (id,min_ts)
            		)
            		CREATE NONCLUSTERED INDEX [NonClusteredIndex-Test_UNIXtime_ID] ON [dbo].[usr_IOBroker_Werte]
            		(
            			[id] ASC,
            			[UnixTime] DESC,
            			[DateTime] DESC
            		)
            		select 'Tabelle mit Index erstellt'
            	END
            
            	
            
            	DROP TABLE IF EXISTS #tempWERTE01	
            	CREATE TABLE #tempWERTE01 (
            		xRowCount int NOT NULL,
            		xId int NOT NULL,
            		xUnixTime bigint NOT NULL,
            		min_ts bigint NULL,
            		max_ts bigint NULL,
            		xZaehler real NULL,
            		CONSTRAINT tempWERTE01_Index UNIQUE  (xid,xUnixTime)
            	)
            	CREATE NONCLUSTERED INDEX ix_tempWERTE01 ON #tempWERTE01 ([xId],[xUnixTime] DESC);
            
            
            	DROP TABLE IF EXISTS #tempWERTE02	
            	CREATE TABLE #tempWERTE02 (
            		xId int NOT NULL,
            		xUnixTime bigint NOT NULL,
            		min_ts bigint NULL,
            		max_ts bigint NULL,
            		xZaehler real NULL,
            		xDiff real NULL,
            		CONSTRAINT tempWERTE02_Index UNIQUE  (xid,xUnixTime)
            	)
            	CREATE NONCLUSTERED INDEX ix_tempWERTE02 ON #tempWERTE02 ([xId],[xUnixTime] DESC,[min_ts]);
            
            
            	
            	-- falls die Tabelle geloescht werden soll
            	if (@ClearAll=-1) 
            	BEGIN
            		if (EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
            		BEGIN
            			if @Debug>0 Select 'IOBroker Werte (Alle) werden alle gelöscht TRUNCATE'
            			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte vor loeschen' from dbo.usr_IOBroker_Werte 
            			TRUNCATE TABLE dbo.usr_IOBroker_Werte
            			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte nach loeschen' from dbo.usr_IOBroker_Werte 
            		END
            	END	
            
            	-- falls xTage von Tabelle geloescht werden sollen
            	if (@ClearAll>0) 
            	BEGIN
            		if (EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
            		BEGIN
            			if @Debug>0 Select 'IOBroker Werte (x-Tage) werden alle gelöscht TRUNCATE'
            			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte vor loeschen' from dbo.usr_IOBroker_Werte 
            			-- nun die x-Tage loeschen
            			--select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
            			select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
            			select @xTemp_Datetime=Dateadd(day,-@ClearAll,DATETIMEFROMPARTS(YEAR(@xNewest_IOWerte),MONTH(@xNewest_IOWerte),DAY(@xNewest_IOWerte),0,0,0,0))
            			select @xTempBigInt=DATEDIFF(SECOND,'01.01.1970 00:00:00.0',@xTemp_Datetime)
            			if @Debug>0 Select @xNewest_IOWerte as 'Neuste Werte in Tabelle @xNewest_IOWerte=:'
            			if @Debug>0 Select @xTemp_Datetime as 'Loesche alles Älter als@xTemp_Datetime=:'
            			if @Debug>0 Select @xTempBigInt as 'Sekunden für Delete Abfrage @xTempBigInt=:'
            
            			if @RunWithoutCopy=0
            			BEGIN
            				DELETE from usr_IOBroker_Werte
            				where
            					UnixTime/1000>=@xTempBigInt
            					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
            			END
            			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte nach loeschen' from dbo.usr_IOBroker_Werte 
            			if @Debug>2
            			BEGIN
            				select 
            					FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(UnixTime),'yy-MM-dd HH:mm:ss') as ts_lesbar_UTC,
            					* 
            				from usr_IOBroker_Werte
            				where
            					UnixTime/1000>=@xTempBigInt
            					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
            			END
            
            		END
            	END	
            
            	-- schauen wir mal ob IOBorker_Werte mnoch leer ist
            	if (NOT EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
            	BEGIN
            	    -- IOBroker leer
            	    if @Debug>0 select 'der Neueste Wert in der Tabelle usc_IOBroker_Werte ist NULL, daher jetzt mal den ältesten Wert in ts_number suchen'
            	    set @xOldest_tsNumber=(select dbo.fn_Convert_UNIX_2_DateTime(min(ts)) from ts_number);
            	    if @Debug>0 select @xOldest_tsNumber as 'Wir nehmen als Startwert den Wert von in ts_number:'
            	    SET @xStartDate= @xOldest_tsNumber
            		-- als EndeDatum setzen wir Startdatum plus die Anzahl der Tage die kopiert werden dürfen laut Übergabe
            		SET @xEndDate=dateadd(day,@MaxDays, @xStartDate)
            		if @Debug>0 select (@MaxDays) as 'Anzahl der Tage die kopiert werden sollen:'
            	END
            	ELSE
            	BEGIN
            		-- Werte in IOBroker vorhanden
            		if @Debug>0 select @MaxDays as 'MaxDays:'
            		
            		-- ermitteln wir wieviele Werte in der Tabelle stehen
            		set @OldValuesCountBeforeDelete=(select count(*) from dbo.usr_IOBroker_Werte)
            
            		-- wir leoschen mal den letzte Stunde in der IOBorkerWerte Tabelle, der sollte meist nur angefangen sein und keine volle Stunde beinhalten
            		select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
            		if @Debug>0 select @xNewest_IOWerte as '@xNewest_IOWerte='
            		if @Debug>0 select dateadd(hour, -1,GETUTCDATE()) as 'dateadd(hour, -1,GETUTCDATE())='
            		
            		if @xNewest_IOWerte>=dateadd(hour, -1,GETUTCDATE())
            		begin
            			if @Debug>0 
            			BEGIN
            				select 'wir loeschenletzte stunde, das wären dann:'
            				
            				SELECT dateadd(SECOND,UnixTime/1000, '01.01.1970 00:00:00.0'),* from usr_IOBroker_Werte
            				where
            					UnixTime/1000>DATEDIFF(SECOND,'01.01.1970 00:00:00.0',Dateadd(hour,-1,@xNewest_IOWerte))
            					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
            			END
            			
            			DELETE from usr_IOBroker_Werte
            			where
            				UnixTime/1000>DATEDIFF(SECOND,'01.01.1970 00:00:00.0',Dateadd(hour,-1,@xNewest_IOWerte))
            				AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
            		END
            		
            		select @xNewest_IOWerte=dbo.fn_Convert_UNIX_2_DateTime(max(min_ts)) from usr_IOBroker_Werte
            		if @Debug>0 select @xNewest_IOWerte as 'usr_IOBroker_Werte vorhanden, hier ist der neueste Wert min_ts:'
            
            		set    @xNewest_IOWerte_AddDays=dateadd(day,@MaxDays,@xNewest_IOWerte)
            		if @Debug>0 select @xNewest_IOWerte_AddDays as 'neuester Wert von usr_IOBroker_Werte + MaxDays:'
            		
            		select @xOldest_ref=dbo.fn_Convert_DateTime_2_ts_sec(@xNewest_IOWerte_AddDays)
            		if @Debug>0 select @xOldest_ref as '@xOldest_ref:'
            		
            		select @xOldest_tsNumber=ISNULL((select dbo.fn_Convert_UNIX_2_DateTime(min(ts)) from ts_number where ts/1000>@xOldest_ref),GETUTCDATE())
            		if @Debug>0 select @xOldest_tsNumber as 'Der älterste Wert von ts_number der größer ist als der neuste IOBroker_Wert Eintrag + MaxDays:'
            
            		SET @xStartDate=dateadd(day,-1, @xNewest_IOWerte)
            		SET @xEndDate=@xOldest_tsNumber
            	END
            	
            	-- falls Start und Ende übergeben, dann machen wir nur das
            	if @StartDate<>'' 
            	BEGIn
            		if @Debug>0 select 'Start und Ende übergeben, Abfrage auf diese Werte begrenzen' 
            		SET @xStartDate=@StartDate
            		SET @xEndDate=@EndDate
            	END
            
            
            /*
            	--- schauen wir mal welche number_ts das betrift
            	if (@Debug>0) 
            	BEGIN
            		select 
            			dbo.fn_Convert_ts_sec2DateTime(ts/1000),
            			* 
            		from ts_number
            		where 
            			(ts/1000) >= @xStartDateUNIX
            			and (ts/1000) <  @xEndDateUNIX
            			and id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
            		order by ts DESC
            	END
            
            	-- Welches Messwwerte schauen wir an?
            
            	if (@Debug>0) 
            	BEGIN
            		select 'ts_number, diese Werte schauen wir an'
            		
            		select 
            			ts as xts,
            			dbo.fn_Convert_UNIX_2_UTC(ts) as ts_in_UTC,
            			FORMAT(dateadd(s,ts/1000,'19700101'),'yy-MM-dd HH:mm:ss') as ts_in_Format_ohne_UTC,
            			@xStartDate as xStartFilter_ts,
            			dbo.fn_ConvertUTC2Local(@xStartDate) as xStartFilter_UTC,
            			@xEndDate as xEndeFilter_ts,
            			dbo.fn_ConvertUTC2Local(@xEndDate) as x@xEndeFilter_UTC,
            			*
            		from ts_number
            		where
            			id = @myId
            			AND ts >= dbo.fn_ConvertUTC2IOBrokerTS(@xStartDate)
            			AND ts <  dbo.fn_ConvertUTC2IOBrokerTS(@xEndDate)
            		order by ts DESC;
            	END
            	*/
            	set @runtimestart=getUTCdate()
            	set @CountAnzahl=0
            
            	while (@CountAnzahl=0 and datediff(SECOND,@runtimestart,getUTCdate())<30)
            	begin
            	if @Debug>0 select 'while schleife startr'
            	if @Debug>0 select  datediff(SECOND,@runtimestart,getUTCdate()) as 'laufzeit'
            
            		-- wir loeschen mal die temporären Tabellen
            		TRUNCATE TABLE #tempWERTE01
            		TRUNCATE TABLE #tempWERTE02
            
            		-- berechnen wir enddatum
            		if @xEndDate>GETUTCDATE()	
            		BEGIN
            			if @Debug>0 select 'Endedatum ist größer als aktuelles Datum, daher mal begrenzen auf aktuelles Datum!'
            			set @xEndDate=GETUTCDATE()
            		END
            	
            		if @Debug>0 select @xStartDate as 'Filter Startzeit'
            		if @Debug>0 select @xEndDate   as 'Filter Endezeit';
            
            		-- un nun Start un Ende als UNIXWert d.h. ohne UTC Verschiebung
            		SET @xStartDateUNIX=[dbo].[fn_Convert_DateTime_2_ts_sec](@xStartDate)
            		SET @xEndDateUNIX=[dbo].[fn_Convert_DateTime_2_ts_sec](@xEndDate)
            	
            		--select dbo.fn_Convert_ts_sec2DateTime(@xStartDateUNIX) as 'Filter @xStartDateUNIX', @xStartDateUNIX as 'as ts'
            		--select dbo.fn_Convert_ts_sec2DateTime(@xEndDateUNIX)   as 'Filter @xEndDateUNIX', @xEndDateUNIX as 'as ts'
            
            		-- und nun mal versuchen die neue Tabelle zu füllen
            		--- wir ermitteln damit nicht ein einfaches MIN oder MAX, das würde mit GROUP schon gehen, sondern
            		-- holen uns den letzten Wert des Tages aus ts_number und speichern diesen
            		-- es wird hier mit xRC doppelte Einträge in ts_number gefiltert, das kann z.B. passieren, wenn zur gleichen Zeit ein Wert vom Adapter kommt und der SQL Server einen Wert schreibt wenn er aufzeichnen soll alle x-sekunden
            
            
            		if @Debug>0 select 'Alle Objekte: ermitteln wir mal die Werte im Intervall 1 h und kopieren diese in #tempWERTE01'
            		insert into #tempWERTE01 
            		(
            			xRowCount,
            			xId, 
            			min_ts,max_ts,
            			xUnixTime,
            			xZaehler
            		)
            		select * from 
            		(
            			SELECT 
            				ROW_NUMBER() OVER(PARTITION BY l.id,l.ts ORDER BY l.ts DESC) xRC,
            				l.id as xId,
            				m.min_ts as min_ts,
            				m.max_ts as max_ts,
            				l.ts as xUnixTime,
            				l.val AS xZaehler
            			FROM ts_number l
            			INNER JOIN 
            			(
            				SELECT
            					MAX(x.id) as xid,
            					x.ts/1000/(60*60) as d,
            					MIN(x.ts) as min_ts,		
            					MAX(x.ts) as max_ts
            				FROM  ts_number x
            				Where 
            					x.id = (CASE WHEN @myId=0 THEN x.id ELSE @myId END)
            					AND (x.ts/1000) >=  @xStartDateUNIX  --AND (x.ts/1000) >= datediff(s, '1970.01.01', @xStartDateUNIX)
            					AND (x.ts/1000) < @xEndDateUNIX
            				GROUP BY 
            					x.id,
            					x.ts/1000/(60*60) -- 1 h
            			) m
            			ON (
            				l.id=m.xid
            				AND l.ts = m.max_ts
            				)
            			WHERE ---shere bezeiht sich auf den gesamten Join
            				--xRC = 1
            				l.id = (CASE WHEN @myId=0 THEN l.id ELSE @myId END)
            				And l.val IS NOT NULL
            				And l.val>=0
            				And	(l.ts/1000) >= @xStartDateUNIX
            				and (l.ts/1000) <  @xEndDateUNIX
            		) aa
            		where aa.xRC=1
            
            
            		if (@Debug>0) 
            		BEGIN
            			select 'temp01 Inhalt anzeigen'
            			select 
            				xUnixTime as xxts,
            				dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as ts_in_UTC,
            				FORMAT(dateadd(s,xUnixTime/1000,'19700101'),'yy-MM-dd HH:mm:ss') as ts_in_Format_ohne_UTC,
            				@xStartDate as xStartFilter_ts,
            				dbo.fn_Convert_UTCDateTime_2_ts_sec(@xStartDate) as xStartFilter_UTC,
            				@xEndDate as xEndeFilter_ts,
            				dbo.fn_Convert_UTCDateTime_2_ts_sec(@xEndDate) as xEndeFilter_UTC,
            				*
            			from #tempWERTE01
            			order by xId  ASC, xUnixTime DESC;
            		END
            
            
            	/*
            		if (@Debug>0) 
            		BEGIN
            			select 'temp01 vor dem Löschen doppelter Werte'
            			SELECT COUNT(*) from #tempWERTE01;
            		END		
            			-- wir loeschen einfach die doppelten werte, falls IOBroker mal zu einem Zeitpunkt sowohl den Messwerte bekommt
            			-- als auch den eingestellten Wert der Aufgezeichnet werden soll im Intervall
            			-- damit verhindern wir beim Insert eine Schlüsselverletzung
            		
            		WITH cte AS (
            			SELECT 
            				xId, 
            				xUnixTime, 
            				ROW_NUMBER() OVER (
            					PARTITION BY 
            						xId, 
            						xUnixTime
            					ORDER BY 
            						xId, 
            						xUnixTime
            				) row_num
            				FROM 
            				#tempWERTE01
            		)
            		DELETE FROM cte
            		WHERE row_num > 1;
            
            		select 'temp01 NACH dem Löschen doppelter Werte'
            		select * from #tempWERTE01;
            	*/
            	
            		-- und nun mal mit der internen SQL Funktion lag - die Differenz zum vorherigen Wert ermitteln
            		--select 'und nun die Differenz immer zum letzten Wert:'
            		insert into #tempWERTE02
            		( xId, min_ts,max_ts, xUnixTime, xZaehler,xDiff )
            		SELECT 
            		  xId, min_ts,max_ts, xUnixTime, xZaehler, 
            		  round((xZaehler-lag(xZaehler) over (partition by xid order by (xUnixTime/1000/(60*60)))),3) -- 1 h 
            		  --(xZaehler-lag(xZaehler) over (partition by xid order by FORMAT(dbo.fn_Convert_UNIX_2_UTC(xUnixTime),'yy-MM-dd HH')))
            		FROM #tempWERTE01 ;
            
            		-- Werte anzeigen
            		if (@Debug>0) 
            		BEGIN
            			select 'Inhalt #tempWerte02 anzeigen:';
            			--set rowcount @MaxCount;
            			Select dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as xUnixTimeUTC,
            			*
            			from #tempWERTE02
            			order by xId ASC, xUnixTime DESC
            		END;
            
            		-- unsinnige Werte anzeigen
            		if (@Debug>0) 
            		BEGIN
            			select 'Unsinnige Inhalt #tempWerte02 anzeigen:';
            			Select dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as xUnixTimeUTC,
            			*
            			from #tempWERTE02
            			where xDiff<0 OR xDiff>(xzaehler*1.5)
            			order by xId ASC, xUnixTime DESC
            		END;
            		
            		-- Sprünge die keinen Sinn machen löschen
            		delete 
            			from #tempWERTE02 
            			where xDiff<0 OR xDiff>(xzaehler*1.5);
            
            		/*
            		-- versuchen wir mal einen totalen Zaehler zu bauen
            		--select 'und nun ergänzen wir einen totalen neuen laufenden Zähler:'
            		select 
            			*,
            			sum(xDiff) over(order by xDay rows unbounded preceding) as xSumTotal,
            			(select name from datapoints where id=rr.xid) as xObject
            		FROM 
            			tempWERTE02 rr;
            		*/
            
            		-- wieviele Werte wären neu?
            		with xAnzahl as (
            		SELECT DISTINCT 
            			s.xId, s.min_ts, s.max_ts, s.xUnixTime, s.xZaehler, s.xDiff	 
            		from #tempWERTE02 s
            		WHERE NOT EXISTS 
            				(SELECT *
            				FROM  dbo.usr_IOBroker_Werte t
            				WHERE 
            					t.id = s.xId
            					--AND t.UnixTime = s.xUnixTime
            					and t.min_ts = s.min_ts   --- hier mal schauen ob der Startwert schon vorhanden ist
            					--and s.xUnixTime IS NOT NULL
            					)
            		)
            		select @CountAnzahl=count(*) from xAnzahl 
            		--select @CountAnzahl=0
            		if @Debug>0 select @CountAnzahl as 'Anzahl der kopierenden werte'
            		if (@CountAnzahl=0)
            		begin
            			set @xEndDate=dateadd(day,@MaxDays,@xEndDate);
            			if @Debug>0 select @xEndDate as 'keine werte erkannt und kopiert, enddate erhöhen!'
            		end
            		else
            		begin
            			break
            		end
            
            		if @xEndDate>GETUTCDATE()	
            		BEGIN
            			if @Debug>0 select 'Endedatum ist größer als aktuelles Datum, daher mal begrenzen auf aktuelles Datum!'
            			break
            		END
            
            		if @EndDate<>''
            		begin
            			if @xEndDate>@EndDate	
            			BEGIN
            				if @Debug>0 select 'Endedatum ist größer als @EndDate, wir stoppen die Schleife!'
            				break
            			END
            		END
            
            End; -- ####### WHILE
            
            	set @OldValuesCount=(select count(*) from dbo.usr_IOBroker_Werte)
            	if (@RunWithoutCopy=0)
            	BEGIN
            		if @Debug>0 select 'Funktion mit RunWithoutCopy=0 gestartet d.h. es werden neue Werte kopiert!'
            		-- Werte in die echte neue Tabelle übernehmen
            		--select 'und nun die Werte in die neue Tabelle kopieren:'
            		set @CurrentTime = DATEDIFF(SECOND,'01.01.1970',getUTCDate())
            		if @Debug>0 select @CurrentTime as '@CurrentTime='
            
            		INSERT  INTO dbo.usr_IOBroker_Werte 
            		(
            			id, create_ts, min_ts, max_ts, UnixTime, [DateTime], Zaehler, Diff
            		)
            		SELECT DISTINCT 
            			s.xId, @CurrentTime, s.min_ts, s.max_ts, s.xUnixTime, dbo.fn_Convert_UNIX_2_UTCDateTime(s.xUnixTime), s.xZaehler, s.xDiff
            		from #tempWERTE02 s
            		WHERE NOT EXISTS 
            				(SELECT *
            				FROM  dbo.usr_IOBroker_Werte t
            				WHERE 
            					t.id = s.xId
            					AND 
            					(
            					t.UnixTime = s.xUnixTime
            					or t.min_ts = s.min_ts
            					)   --- hier mal schauen ob der Startwert schon vorhanden ist
            					--and s.xUnixTime IS NOT NULL
            				);
            	END
            	ELSE
            	BEGIN
            		if @Debug>0 select 'Funktion mit RunWithoutCopy gestartet d.h. es werden keine neuen Werte kopiert'
            	END
            
            		
            	set @NewValuesCount = (select count(*) from dbo.usr_IOBroker_Werte)
            	select 
            		@xStartDate as 'Startzeit', 
            		@xEndDate as 'Endezeit', 
            		(@NewValuesCount-@OldValuesCount) as 'Created', 
            		(@NewValuesCount-@OldValuesCountBeforeDelete) as 'New', 
            		@NewValuesCount as 'WerteIOBrokerTable'
            
            		
            	if (@Debug>=2) 
            	BEGIN
            		select 'alle werte in IOBroker_Werte anzeigen'
            		SELECT TOP 1000
            			dbo.fn_Convert_ts_sec_2_UTCDateTime(create_ts) as create_ts_UTC,
            			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(UnixTime),'yy-MM-dd HH:mm:ss') as ts_lesbar_UTC,
            			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(max_ts),'yy-MM-dd HH:mm:ss') as xMax_UTC,
            			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(min_ts),'yy-MM-dd HH:mm:ss') as xMin_UTC,
            			*
            		from usr_IOBroker_Werte
            		where
            			Id = (CASE WHEN @myId=0 THEN Id ELSE @myId END) -- DEBUG
            		order by UnixTime desc
            
            		--select count(*) as 'Anzahl Werte in IOBroker_Werte' from dbo.usr_IOBroker_Werte 
            	END;
            	
            	
            	-- wir loeschen nun alles temporäre
            	drop table #tempWERTE01
            	drop table #tempWERTE02
            
            
            	COMMIT TRANSACTION
            END
            
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post

            Support us

            ioBroker
            Community Adapters
            Donate

            934
            Online

            31.8k
            Users

            80.0k
            Topics

            1.3m
            Posts

            2
            4
            261
            Loading More Posts
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes
            Reply
            • Reply as topic
            Log in to reply
            Community
            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
            The ioBroker Community 2014-2023
            logo