Skip to content
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. SQL Timeout von 15 sek erhöhen

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.0k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.8k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.0k

SQL Timeout von 15 sek erhöhen

Scheduled Pinned Locked Moved JavaScript
4 Posts 2 Posters 369 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    thomassch
    wrote on last edited by
    #1

    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

    ******* iobroker auf Intel PC, Raspberry PI4 + Homematic CCU *******

    F 1 Reply Last reply
    0
    • T thomassch

      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 Offline
      F Offline
      fastfoot
      wrote on last edited by
      #2

      @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

      iobroker läuft unter Docker auf QNAP TS-451+
      SkriptRecovery: https://forum.iobroker.net/post/930558

      T 1 Reply Last reply
      0
      • F fastfoot

        @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 Offline
        T Offline
        thomassch
        wrote on last edited by
        #3

        @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

        ******* iobroker auf Intel PC, Raspberry PI4 + Homematic CCU *******

        T 1 Reply Last reply
        0
        • T thomassch

          @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 Offline
          T Offline
          thomassch
          wrote on last edited by
          #4

          @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
          
          

          ******* iobroker auf Intel PC, Raspberry PI4 + Homematic CCU *******

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          Support us

          ioBroker
          Community Adapters
          Donate

          624

          Online

          32.4k

          Users

          81.3k

          Topics

          1.3m

          Posts
          Community
          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
          ioBroker Community 2014-2025
          logo
          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Recent
          • Tags
          • Unread 0
          • Categories
          • Unreplied
          • Popular
          • GitHub
          • Docu
          • Hilfe