Jump to content

hh2000

Members
  • Gesamte Inhalte

    550
  • Registriert seit

  • Letzter Besuch

Beiträge erstellt von hh2000

  1. Moin,

     

    wenn du eine Variable in einem SELECT zuweist (> SELECT @Variable = Zelle FROM inserted) war die Frage was passiert, wenn im Statement mehrere Zeilen als Ergebnis vorkommen.

    Die Variable speichert ja nur einen Wert, die Anzahl der Datensätze in inserted ist aber größer 1.

     

    Genauso kann es passieren, dass dein Insert-Statement kein Datensatz einfügt, weil die Bedingung nicht erfüllt ist. Der Trigger wird dann aber trotzdem ausgelöst:

    INSERT INTO Tabelle (...)
    SELECT ...
    FROM NochneTabelle
    WHERE 1=2
    

    Trigger wird gestartet, dein o.g. "SELECT @Variable = Zelle FROM inserted" ergibt dann @Variable = NULL Bei SQL immer mengenbasiert denken, nicht zeilenweile (ok, da gibt es auch Möglichkeiten), daher der Einwand was passiert beim Einfügen von keinem , einem oder mehreren Datensätzen.

     

    Gruß Kai

  2. Moin,

     

    ist das ein "Instead of" oder "After" Trigger?

     

    Biite immer bedenken, das beim Einfügen kein, ein oder mehrere Datensätze möglich sind. Das muss der Trigger

    verarbeiten können. Unbedingt den Trigger auf diese Fälle prüfen.

    > SELECT @Variable = Zelle FROM inserted

    Was passiert mit @Variable, wenn du mehr als einen Datensatz verarbeitest?

     

    Schöner ware etwas wie:

    IF EXISTS ( SELECT * FROM inserted Where ....)
    BEGIN
     ... Tut hier was
    END

    Du kannst zum prüfen auch inserted mit anderen Tabellen JOINen, um dann weitere Aktionen durchzuführen.

     

    > beim eingefügten Datensatz sind einige Zellen mit NULL

     

    Hast Du evtl. noch andere Befehle im Trigger die die Tabelle inserted manipulieren ?

    Ob der xp_cmdshell hier evtl. noch andere Nebenwirkungen bei bestimmten Bedingungen hat, weiß ich leider nicht.

     

    Gruß Kai

  3. Das sieht von der Struktur her schonmal gut aus.

     

    Nur als Tipp:

     

    - Betrachte jedes SELECT Statement für sich und bewerte das Ergebenis

     

    - kontrolliere nochmal den JOIN (evtl. Copy-Paste Fehler)

     

    - kommen die Daten aus der jeweils richtigen Spalte

     

    - kontrolliere den WHERE String, oben hast du noch von 'EVARFFOLIENNUMMER%' gesprochen, der taucht hier aber nicht mehr auf.

     

    Gruß Kai

  4. ... die im Feld "KEYIPAR1 mit "EVARFFOLIENNUMMER%" als Schlüssel haben? ...

     

    einfach ein     

    OR KEYIPAR1 like 'EVARFFOLIENNUMMER%'

    anhängen (OR, AND, siehe Onlinehilfe):

    join tbl_par on tbl_par.parlfd2 = tbl_vbs.VBSFOLET
    
    where KEYIPAR1 like 'EVARFFOLIENETIKET%'
    OR KEYIPAR1 like 'EVARFFOLIENNUMMER%'

    Sollte allerdings 'EVARFFOLIENNUMMER%' eine feste Zeichenkette sein, so solltest Du  statt "like" lieber "=" benutzen ("like" funktioniert hier aber auch).

     

    Gruß Kai

  5. Moin,
     
    als Anregung, die Abfrage
     

    SELECT TOP 1 ArtikelNr, Preis
    FROM T_Tabelle 
    ORDER BY Datum DESC
    WHERE Artikel = 4711
    

     
    ergibt den gesuchten aktuellen Preis für _einen_ Artikel.
    Das kann man z.B. in eine korrelierende Unterabfrage einbauen:
     

    SELECT ArtikelNr, ( SELECT TOP 1 Preis 
                        FROM T_Tabelle B 
                        ORDER BY Datum DESC 
                        WHERE B.ArtikelNr = A.ArtikelNr
                      ) AS AktuellerPreis
    FROM T_Tabelle A
    

     
    Evtl. noch GROUP BY je nach Bedarf
     
    Gruß Kai

  6. Moin,

     

    das wären m.E. die verschiedenen Ansätze zu Deinen Fragen:

     

    -- Kunden die gar nicht in Tabelle 2 (T2) enthalten sind:
    SELECT Tabelle1.*
    FROM Tabelle1
    WHERE Tabelle1.Kunde NOT IN (
        SELECT Kunde
        FROM Tabelle2
    )

    -- Kunden die keine Artikel in Tabelle 2 (T2) haben:
    SELECT Tabelle1.*
    FROM Tabelle1
    WHERE Tabelle1.Artikel NOT IN (
        SELECT Artikel
        FROM Tabelle2
        WHERE Tabelle1.Kunde = Tabelle2.Kunde
    )
    -- Kunden die sowohl in T1 als auch in T2 Artikel die gleichen Artikel haben
    SELECT Tabelle1.*
    FROM Tabelle1
    INNER JOIN Tabelle2
    ON Tabelle1.Kunde = Tabelle2.Kunde
    AND Tabelle1.Artikel = Tabelle2.Artikel
     

     

    ggf. doppelte Datensätze / Sortierung sind nicht berücksichtigt.

     

    Gruß Kai

  7. Moin,

     

    ohne auf das Subselect einzugehen, müsste ein weiteres GROUP BY ausreichen:

        SELECT 
        	System_Typ, count(*) as System_Zugriffe_Monat_NB 
        	FROM(
        		SELECT 
        		SUBSTRING([Ev_Station],1,2) as System_Typ
        		FROM [TEST].[dbo].[EVENTHISTORY]
        		WHERE
        				CAST(substring(CONVERT(varchar(10),[Ev_Time],101),1,2) as numeric) = @paraMonat
        				and cast(substring(CONVERT(varchar(10),[Ev_Time],101),7,4) as numeric) = @paraJahr 
        				and Ev_User !='Unbestimmter Benutzer' 
        				and Ev_User != 'Guest'
        				--and SUBSTRING([Ev_Station],1,2)='NB'
        				
        				group by [Ev_User],[Ev_Station],SUBSTRING([Ev_Station],1,2)
            ) z 
            GROUP BY System_Typ
    

    Gruß Kai

     

    PS: Funktionieren mit der Spalte "Ev_Time" keine Datumsfunktionen?

     

  8. Moin,

     

    ich würde unter SQL immer versuchen _keine_ While-Schleifen oder sehr viele Subselects einzusetzen.

     

    Zerlege das Problem in kleine Schritte und schau dir jeweils die Zwischenergebnisse an:

    - Annahme: die Zählerstande sind aufsteigend, das Feld Datum enthält das Datum zum Messwert.

     

    1 .View mit den Monatszählerständen (hier nur ein Zähler):

     

    SELECT YEAR([Datum]) as Jahr, MONTH([Datum]) as Monat,
          MAX([Zaehler_1K1_1]) AS AktuellerMonat
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS AktMonat
    GROUP BY YEAR([Datum]), MONTH([Datum])
     

    2. "Hilfs"-View mit den Vormonatswerten in der aktuellen Monatszeile.

    Das DATEADD dient nur dazu, die Monat- / Jahresspalten anders darzustellen (Monat + 1):

     

    SELECT YEAR(DATEADD(mm, 1, [Datum]) as Jahr, MONTH(DATEADD(mm, 1, [Datum]) as Monat,
          MAX([Zaehler_1K1_1])
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS VorMonat
    GROUP BY YEAR(DATEADD(mm, 1, [Datum]), MONTH(DATEADD(mm, 1, [Datum])
     

    3. Hinzufügen zweier Hilfsspalten:

     

    SELECT YEAR([Datum]) as Jahr, MONTH([Datum]) as Monat,
          MAX([Zaehler_1K1_1]) AS AktuellerMonat, 0 AS Vormonat
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS AktMonat
    GROUP BY YEAR([Datum]), MONTH([Datum])
     
    
    SELECT YEAR(DATEADD(mm, 1, [Datum]) as Jahr, MONTH(DATEADD(mm, 1, [Datum]) as Monat,
          0, MAX([Zaehler_1K1_1])
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS VorMonat
    GROUP BY YEAR(DATEADD(mm, 1, [Datum]), MONTH(DATEADD(mm, 1, [Datum])
     

    Beide Tabelle haben nun das gleiche Format:

    Jahr, Monat, AktuellerMonat, Vormonat

    Mittels UNION ALL beide Views zusammenfügen und per erneutem GROUP BY

    gruppieren. So würde dann der fertige View aussehen:

     

    SELECT Jahr, Monat, SUM(AktuellerMonat), SUM(Vormonat), SUM(AktuellerMonat) - SUM(Vormonat) AS Differenz
    FROM (
    SELECT YEAR([Datum]) as Jahr, MONTH([Datum]) as Monat,
          MAX([Zaehler_1K1_1]) AS AktuellerMonat, 0 AS Vormonat
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS AktMonat
    GROUP BY YEAR([Datum]), MONTH([Datum])
    UNION ALL
    
    
    
    SELECT YEAR(DATEADD(mm, 1, [Datum]) as Jahr, MONTH(DATEADD(mm, 1, [Datum]) as Monat,
          0, MAX([Zaehler_1K1_1])
    FROM [SKEMS-HST-POWER].[dbo].[EnergieMonat] AS VorMonat
    GROUP BY YEAR(DATEADD(mm, 1, [Datum]), MONTH(DATEADD(mm, 1, [Datum])
    ) a 
    GROUP BY Jahr, Monat
     
    Für weitere Zähler die Zeilen "MAX([Zaehler_1K1_1]) AS AktuellerMonat, 0 AS Vormonat" und

    "0, MAX([Zaehler_1K1_1])" kopieren und die Aliasnamen anpassen.

     

     

    Gruß Kai

  9. Moin,

     

    Cursor sollten nur für Probleme genutzt werden, die nicht mit "normalen" SQL gelöst werden

    können (mengenbasiert <> zeilenorientiert).

     

    Korrekte Rechte auf den verschiedenen Datenbanken vorausgesetzt, könnte das so aussehen (Vollqualifizierter Bezeichner):

    SELECT * FROM DB1.dbo.stammdaten
    UNION ALL
    SELECT * FROM DB2.dbo.stammdaten
    UNION ALL
    SELECT * FROM DB3.dbo.stammdaten
    
    ...
    

    siehe auch SQL-Onlinehilfe "Bezeichner"

     

    Gruß Kai

  10. Moin,

     

    das könnte so aussehen:

    SELECT
       tab_alles.fil as Filiale
       tab_alles.name as Sachbearbeiter
       COUNT (tab_alles.name) as Anzahl_pro_Sachbearbeiter 
       SUM (tab_alles.pos) as Positionen_pro_Sachbearbeiter
       DATEPART (Month, tab_alles.datum) as Monat
    FROM (
      SELECT tab1.fil, tab1.name, tab1.pos, tab1.datum
      WHERE tab1.datum BETWEEN ('01-01-2013') AND ('31-12-2013')
      UNION ALL
      SELECT tab2.fil, tab2.name, tab2.pos, tab2.datum
      WHERE tab2.datum BETWEEN ('01-01-2013') AND ('31-12-2013')
    ) tab_alles
    GROUP BY DATEPART(Month,tab_alles.datum), tab_alles.fil, tab_alles.name

    Gruß Kai

  11. Moin,

     

    - ja, du kannst mehrere Insert Trigger in einer Tabelle installieren (Auswirkung, Nebenwirkung?).

    - ja, du kannst mittels Trigger alte Angebote updaten

     

    Aber,

    - du kannst ganz schnell (schneller als einem lieb ist) die Daten der Tabelle komplett schrotten!

    - bei einem Strukturupdate funktioniert das ganze nicht mehr

     

    Ich empfehle hier Lektüre oder Onlinehilfe bezüglich Trigger mit seinen

    Hilfstabellen INSERTED und DELETED, das lohnt sich wirklich.

     

    So schön Trigger auch sind (ich benutze sie auch), ist ein genaues Wissen inkl. Tests

    nötig, z.B. beim Insert-Trigger das testen von

    einfügen von keinem, einem und mehreren Datensätzen.

     

    Noch als Warnung, bei einem schlechten Test des Trigges fällt Dir evtl. ein Fehler erst später auf, weil dann eine

    Bedingung eintritt die du nicht bedacht hast und der Trigger mehr geändert hat, als er sollte. Ergebnis: Tabellendaten sind Schrott

     

    Gruß Kai

  12. Moin,

     

    der beste Weg wäre wohl, wie schon hier vorgeschlagen wurde, eine Produktionsnummer mit in die Tabelle aufzunehmen.

     

    Die andere Lösung (nicht so schön) könnte so aussehen:

     

    Vorausetzungen:

    - ID ist chronologisch

    - eine Produktion ist immer zusammenhängend in der Tabelle vorhanden

    - es wird nur der aktuelle Type ermittelt

     

    SELECT SUM(Anzahl)
    WHERE ID > (

      SELECT MAX(ID)   -- letzte, höchste ID aller anderen Types
      FROM Tabelle
      WHERE Type NOT IN (

     

         SELECT TOP 1 Type    -- aktueller Type = letzte Zeile in der Tabelle
         FROM Tabelle
         ORDER BY ID DESC
      )
    )

     

    Der innerste Select (Ergebnis eine Zeile) ermittelt den aktuellen Type. Daraufhin wird die höchste ID aller

    anderen Types ermittelt (deine Grenze).

    Dann noch die Werte aller größeren ID summieren.

     

    Ist nicht getestet, gerade was die Laufzeit betrifft.

     

    Gruß Kai

  13. Moin,

     

    wie Dukel schon schrieb, gibt es min. 2 Varianten:

     

    1. Mit DatumVon und DatumBis in der Preistabelle

    - es muss bei der Eingabe drauf geachtet werden, dass keine "Lücken" im Datum entstehen

    - einfachere Abfrage

     

    2. ÄnderungsDatum

    - einfacheres Eingeben

    - kompliziertere Abfrage

     

    Beispiel für Nr. 2:

     

    T_Artikel

    --------------------
    [ArtikelID] Primary Key
    [ArtikeName]

    T_Preis

    ---------------------
    [PreisID] Primary Key
    [ArtikelID] Foreign Key, verweist auf ArtikelID in Tabelle T_Artikel
    [GueltigAb]
    [Preis]


    Abfrage zum ermitteln des Preises zum Zeitpunkt XX (könnte auch in der Zukunft liegen):

    SELECT a.ArtikelID, a.ArtikelName,
          (SELECT TOP 1 p.Preis
           FROM T_Preis p
           WHERE a.ArtikelID = p.ArtikelID
           AND p.GueltigAb <= XX
           ORDER BY p.GueltigAb DESC
          )  AS Preis
    FROM T_Artikel a
    WHERE a.ArtikelID = 123456789
     

    Artikel die noch keinen Preis haben, werden mit NULL in der Spalte [Preis] angezeigt.

     

    Gruß Kai

  14. Moin,

     

    du könntest das mit "PATINDEX" http://msdn.microsoft.com/en-us/library/ms188395.aspx machen. Der Befehl sucht z.B. in einer Spalte eine Zeichenfolge und gibt Dir die erste gefundene Position aus. Dann könntest Du temporär das erste gefundene

    "Berlin" ersetzen und nochmals den neuen String nach "Berlin" durchsuchen. Findet er nichts mehr weißt du, das "Berlin" nur einmal vorhanden ist (und wirst wohl nichts ersetzen).

    Findet er noch ein weiteres "Berlin", kann nach Deiner Definition das erste dann ersetzt werden.

     

    Um das ganze dann in einem SQL-Befehl unterzubringen, kommt zur Entscheidungsfindung noch "CASE WHEN" ins Spiel ...

     

    Gruß Kai

  15. :suspect:

     

    :rolleyes:aha... soweit war ich auch schon....

    NATÜRLICH... :schreck:... du hast vollkommen recht....

     

    Keep it simple!

     

    Habe seit gestern auch ne Lösung gefunden.

    Problem war, dass die Entwickler zwichen dem From und dem With kein Space sondern TAB verwendet haben.

    Manchmal auch zwischen With und (TABLOCKX).

     

    Mein Filter den ich definiert hatte lieferte keine Ergebnisse.

    WHERE sysc.definition LIKE  '% with %(TABLOCKX) %'

     

    VG Frank

     

    Du hast noch zusätzliche Leerzeichen im SuchString. Das passt dann nicht auf z.B. "WITH{CRLF}TABLOCKX"

    WHERE sysc.definition LIKE '%WITH%TABLOCKX%'

    Der sollte genau das gewünschte finden.

     

    Gruß Kai

  16. Moin,

    ist etwas abstrakt was du da möchtest. Denke mal über eine

    Normalisierung der Daten nach, wenn das möglich ist.

     

    Ähnliche Beispiele die evtl. weiterhelfen, die korrekten Befehle hast du ja schon genannt:

     

    http://www.mcseboard.de/ms-sql-server-forum-81/string-teile-feldes-selektieren-185551.html

     

    http://www.mcseboard.de/ms-sql-server-forum-81/suchen-loeschen-bestimmter-zeichenanzahl-182008.html

     

    Gruß Kai

  17. Moin,

     

    Das sollte auch nur ein Denkanstoß sein ;)

     

    ja das hab ich mir schon gedacht :-)

    Ich fand dann die Fragestellung spannend und wollte die dann auch komplett lösen.

    Also im Ansatz glaub ich habe ich verstanden worauf du hinaus willst, allerdings kriege ich das so nicht hin...

     

    Guck Dir mal das Ergebnis der Abfrage mit dem Group By separat an.

    Das gibt Dir eine Tabelle zurück, die das Datum und den Maxwert in einer Zeile liefert.

     

    - INNER JOIN (siehe Onlinehilfe) verknüpft 2 oder mehr Tabellen miteinander

    - Die Schreibweise (SELECT ... ) b "übergibt" das Ergebnis an "INNER JOIN", der das Ergebnis wie eine Tabelle behandelt.

     

    Komplette Tabelle ("a") enthält z.B.

    Datum Uhr Wert

    12.05.2012 11:15 47

    12.05.2012 12:25 11

    12.05.2012 11:58 55

     

    Unser View ("b") enthält dann:

    Datum Wert

    12.05.2012 55

     

    nun JOINe beide miteinander mittels Datum und Uhrzeit (siehe ON im INNER JOIN-Statement), stell Dir beide Ergebnisse nebeneinander vor:

     

    a b

    a.Datum a.Uhr a.Wert b.Datum b.Wert

    12.05.2012 11:15 47

    12.05.2012 11:25 11

    12.05.2012 11:58 55 12.05.2012 55 <- Treffer des INNER JOIN

     

    da hast du nun die eine Zeile

     

    12.05.2012 11:58 55

     

    als Ergebnis vorliegen (Doppelte Zeilen können bei gleichen MaxWerten pro Datum auftreten).

     

    Gruß Kai

×
×
  • Neu erstellen...