none
SQL Abfrage optimieren RRS feed

  • Frage

  • Hallo an alle,

    ich habe immer wieder die Notwendigkeit in die Zukunft und in die Vergangenheit außerhalb eines Zeitbereiches zu schauen. Klingt komisch? Ist auch so!

    declare @Timestamp varchar(30)
    set @Timestamp = CONVERT (datetime,'2017-04-23 00:00:00.000', 121);
    
    declare @Timestamp_END varchar(30)
    set @Timestamp_END = CONVERT (datetime,'2017-05-30 00:00:00.000', 121);
    
    With Vorberechnung as
    (
    SELECT V.[ID]
          ,V.[TimeStamp_Start]
          ,V.[TimeStamp_Stop]
    	  ,V.Verwendung
      FROM [SKEMS-HST].[dbo].[Produktionszeiten] as V
        	--WHERE (TimeStamp_Start Between CONVERT (datetime,'2016-04-23 00:00:00.000', 121) 
    	WHERE (TimeStamp_Start Between
    	CONVERT (datetime, CONVERT (datetime, CAST(CONVERT (VARCHAR(11), @Timestamp, 106) AS varchar) + ' 00:00:00.000', 106), 121) 
    	and CONVERT (datetime, CONVERT (datetime, CAST(CONVERT (VARCHAR(11), @Timestamp_End, 106) AS varchar) + ' 23:59:59.000', 106), 121) 
    	)	
    )
    
    SELECT V.ID, V.[TimeStamp_Start], V.[TimeStamp_Stop]
          ,min([PCC_Milchtemp_FB6_1]) as Min_Temp
          ,max([PCC_Milchtemp_FB6_1]) as Max_Temp
    	  ,V.Verwendung
    	 
    	  ,DATEADD(minute,-1,[TimeStamp_Start]) as [TimeStamp_Start_m1]
    	  ,DATEADD(minute,+1,[TimeStamp_Stop]) as [TimeStamp_Stop_p1]
    	 	
    FROM [SKEMS-HST].[dbo].[TREND009] AS T1
    
    INNER JOIN Vorberechnung as V
    	on [Time_Stamp]  between V.[TimeStamp_Start] and V.[TimeStamp_Stop]
    	
    	group by ID,TimeStamp_Start,TimeStamp_Stop,Verwendung 
    
    

    Nach dem ich also nun auch TimeStamp_Start_m1 und TimeStamp_Stop_p1 herausgefunden habe möchte ich diese Zeitpunkte nutzen für eine andere Abfrage. So zu sagen eine zusätzliche. Und ich hoffe da könnt ihr mir helfen. Meine Kenntnisse sind dafür zur beschränkt!

    Wie könnte ich denn folgende SQL Abfrage zusätzlich mit unterbekommen?

    SELECT V.ID, V.[TimeStamp_Start], V.[TimeStamp_Stop]
    	,T1.[Füllstand_FB6_1] as [Fuellstand_Stop]
    
    FROM [SKEMS-HST].[dbo].[TREND009] AS T1
    
    INNER JOIN Vorberechnung as V
    
    	on [Time_Stamp] = V.[TimeStamp_Stop_p1]  
    group by V.ID, V.[TimeStamp_Start],V.[TimeStamp_Stop],T1.[Füllstand_FB6_1]

    Mittwoch, 10. Mai 2017 15:10

Alle Antworten

  • Hallo Toot,

    die zweite Abfrage schaut mir nicht ganz stimmig aus.

    Ich vermute, dass es sich bei Füllstand_FB6_1 aka. Fuellstand_Stop einen bzw. mehrere numerische(n) Wert(e) handelt, der im angegebenen Bereich (aus Abfrage 1) liegen soll. Diesen in die GROUP BY Klausel aufzunehmen wäre widersinnig. Damit werden Duplikate ausgeblendet (vergleichbar DISTINCT) oder wiederum unnötige Werte ausgeben, wenn man nur den ersten, letzten etc. haben will.

    Etwas Aufklärung worum es sich dabei handelt, könnte helfen.

    Weiter wäre die Frage, ob Du zwei Abfragen / Ausgaben haben willst, oder ob Du die beiden zu einer einzige vereinigen möchtest. Ersteres (zwei Abfrage) ginge in dem man daraus einen Stapel[1] macht und die beiden Kriterien vorher in Variablen speichert. Zweiteres wäre - wenn obiges klar ist - u. U. über CROSS APPLY lösbar, so dass man die Zusatz-Daten parallel zu denen aus der ersten sieht.

    Gruß Elmar

    [1] Besser als einen adhoc Stapel zu nutzen wäre u. U. gleich eine "richtige" Prozedur daraus zu machen.

    Mittwoch, 10. Mai 2017 18:13
  • Hallo Elmar,

    danke für deine Antwort. Zu der 2.ten SQL Abfrage (mit Füllstand_FB6_1) sei gesagt das diese eigentlich den gleichen Zeitbereich nutzt wie die erste Abfrage. Jedoch eben eine Minute in die Vergangenheit und eine Minute in die Zukunkt. Genau das würde ich eben gern abbilden bzw. eben abfragen. Jedes mal dafür Funktionen oder Prozeduren zu schreiben geht natürlich(mach ich auch aktuell) jedoch würde es mich interessieren dies in einer Abfrage zu machen.

    Es geht hier eben vor allem um den Wissenszuwachs.

    Donnerstag, 11. Mai 2017 11:24
  • Hallo Toot,

    je länger ich darauf geguckt habe, umso mehr hätte ich mir Testdaten gewünscht.

    Die "Vorberechnung" ist IMHO nicht wirklich nützlich, eher das Resultat der Datumsberechnung. Die kann man vereinfachen, in dem man mit DATE arbeitet und auf das BETWEEN verzichtet - was bei datetime wegen der krummen Millisekunden immer problematisch ist.

    Das zweimalige Einbinden der TREND009 Tabelle in unterschiedlichem Zeitfenstern kann auch via weiterem JOIN erfolgen. Derzeitiger Stand  hier- ohne Test, als reines Gedankenspiel:

    -- vereinfacht mit DATE und Addition eines Tages (vermeidet Randbedingungen)
    DECLARE 
    	@TimeStamp_Start date = '2017-04-23',
    	@TimeStamp_Ende date = '2017-05-30';
    
    WITH Vorberechnung AS
    (
    	SELECT V.[ID]
    		, V.[TimeStamp_Start]
    		, V.[TimeStamp_Stop]
    		, V.Verwendung
    	FROM [dbo].[Produktionszeiten] AS V
    	WHERE (TimeStamp_Start >= @TimeStamp_Start
    		AND TimeStamp_Start < DATEADD(DAY, 1, @TimeStamp_Ende))
    )
    SELECT V.ID
    	, V.[TimeStamp_Start]
    	, V.[TimeStamp_Stop]
    	, V.Verwendung
    
        , MIN([PCC_Milchtemp_FB6_1]) AS Min_Temp
        , MAX([PCC_Milchtemp_FB6_1]) AS Max_Temp
    	 
    	, DATEADD(minute, -1, [TimeStamp_Start]) AS [TimeStamp_Start_m1]
    	, DATEADD(minute, +1, [TimeStamp_Stop]) AS [TimeStamp_Stop_p1]
    
    	, (SELECT
    			MAX(T2.[Füllstand_FB6_1])
    		FROM [dbo].[TREND009] AS T2
    		WHERE T2.[Time_Stamp] >= DATEADD(MINUTE, -1, V.[TimeStamp_Start])
    		  AND T2.[Time_Stamp] < DATEADD(MINUTE, +1, V.[TimeStamp_Stop])
    	  ) AS [Fuellstand_Stop]
    
    FROM [dbo].[TREND009] AS T1
    INNER JOIN Vorberechnung AS V
    	ON	T1.[Time_Stamp] >= V.[TimeStamp_Start] 
    	AND T1.[Time_Stamp] < V.[TimeStamp_Stop]
    GROUP BY V.ID, V.TimeStamp_Start, V.TimeStamp_Stop, V.Verwendung;
    
    
    -- OHNE CTE, da nur für als Filter verwendet 
    -- (sieht für mich verständlicher aus ;)
    SELECT P.ID
    	, P.[TimeStamp_Start]
    	, P.[TimeStamp_Stop]
    	, P.Verwendung
    
        , MIN(T1.[PCC_Milchtemp_FB6_1]) AS Min_Temp
        , MAX(T1.[PCC_Milchtemp_FB6_1]) AS Max_Temp
    	 
    	, MAX(T2.[Füllstand_FB6_1]) AS [Fuellstand_Stop]	-- oder MIN?
    
    	, DATEADD(minute, -1, P.[TimeStamp_Start]) AS [TimeStamp_Start_m1]
    	, DATEADD(minute, +1, P.[TimeStamp_Stop]) AS [TimeStamp_Stop_p1]
    
    FROM [dbo].[Produktionszeiten] AS P
    INNER JOIN [dbo].[TREND009] AS T1
    	ON	T1.[Time_Stamp] >= P.[TimeStamp_Start] 
    	AND T1.[Time_Stamp] < P.[TimeStamp_Stop]
    LEFT JOIN [dbo].[TREND009] AS T2	-- evtl. INNER JOIN möglich
    	-- "Fenster" wie oben [TimeStamp_Start_m1], [TimeStamp_Stop_p1]
    	ON  T2.[Time_Stamp] >= DATEADD(MINUTE, -1, P.[TimeStamp_Start])
    	AND T2.[Time_Stamp] < DATEADD(MINUTE, +1, P.[TimeStamp_Stop])
    WHERE (TimeStamp_Start >= @TimeStamp_Start 
    	AND TimeStamp_Start < DATEADD(DAY, 1, @TimeStamp_Ende))
    -- GROUP BY ist evtl. unnötig --> z. B. Trend via CROSS APPLY (möglich?) 
    GROUP BY P.ID, P.TimeStamp_Start, P.TimeStamp_Stop, P.Verwendung;
    

    Die erste Abfrage verwendet eine Unterabfrage um den Füllstand" zu ermitteln, die zweite lässt die "Vorberechnung" fallen und verwendet anstatt dessen die Tabellen direkt. Ob das richtige rauskommt, müsstest Du testen und ggf. den einen oder anderen Vergleich anpassen.

    Wobei mir das GROUP BY in den Abfragen aufstößt. Es müsste eigentlich eliminierbar sein, in dem man die "Trends" via CROSS APPLY an die Produktionszeiten anbindet. Dafür ist mir die Datenlage jedoch derzeit zu unklar:

    Mit welchen Zeitraster erfolgt die Ablage der "Timestamps" in den Tabellen?

    Wie viele Überschneidungen können sich dabei ergeben?

    Gruß Elmar

    Freitag, 12. Mai 2017 08:17
  • Danke Elmar das du so hartnäckig bleibst und mir bei der Lösung hilfst! Leider ist, wie so oft im Leben, mir eine höhere Priorität in einen anderen Fall zugewiesen wurden. So muss ich dieses Thema erst einmal ruhen lassen. Ich melde mich aber wieder wenn ich an diesem Thema weiter arbeiten kann.
    Mittwoch, 17. Mai 2017 06:30