Announcement

Collapse
No announcement yet.

0-Zeile anzeigen bei COUNT mit ODER

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • 0-Zeile anzeigen bei COUNT mit ODER

    Hallo alle zusammen!

    Ich habe folgendes Problem bei der Erstellung eines SELECT-Statements.
    Leider werden bislang nur die Zeilen zurückgegeben, wo der COUNT > 0 ist.
    Ich hätte jedoch auch gerne eine Zeile im Ergebnis-Set, wenn der Count = 0 ist.
    Das meine Abfrage das richtige tut und demzufolge "logisch falsch ist", ist mir klar. Mir fehlt bislang der richtige Weg zur Umsetzung.

    Die Tabelle, um die es geht, sieht vereinfacht wie folgt aus:
    Code:
    CREATE TABLE [dbo].[TBL_LWDaten_ARCHIV] (
      [ID_ARCHIV] numeric(18, 0) IDENTITY(1, 1) NOT NULL,
      [LW-Nr] int NOT NULL,
      [Sektor] int NOT NULL,
      [letzte Lesestelle] int NOT NULL,
      [Sektorzeit] datetime NOT NULL,
      [Leerwagen] bit NOT NULL,
      CONSTRAINT [TBL_LWDaten_ARCHIV_PK] PRIMARY KEY CLUSTERED ([ID_ARCHIV])
    )
    ON [PRIMARY]
    GO
    Mein derzeitiges Abfrage-Statement sieht wie folgt aus:
    Code:
    SELECT top 100 PERCENT 
    CASE l.[letzte Lesestelle]
    	WHEN 112 THEN '01. Aufgabe 1'
    	WHEN 120 THEN '02. Aufgabe 2'
    	WHEN 148 THEN '03. Aufgabe 3'
    	WHEN 156 THEN '04. Aufgabe 4'
    	WHEN 219 THEN '05. Strahlanlage'
    	WHEN 237 THEN '06. Vorbehandlung'
    	WHEN 603 THEN '07. Pulverkabine 1'
    	WHEN 703 THEN '08. Pulverkabine 2'
    	WHEN 812 THEN '09. Pulverofen 1 HT'
    	WHEN 819 THEN '10. Pulverofen 2 NT'
    END AS Position,
    COUNT([letzte Lesestelle]) AS [Anz LW] 
    FROM -- Auswertungszeitraum vorgeben
    dbo.fn_Get_LWDaten_Archiv_TimeExtract ('18.11.2010', '10:00:00', '19.11.2010', '23:59:59') AS l
    WHERE 
    (-- Aufhängestation 1..4
    	(l.[letzte Lesestelle] IN (112, 120, 148, 156)) AND (l.Leerwagen = 0)
    ) OR
    (-- Strahlanlage
    	(l.[letzte Lesestelle] IN (219)) AND (l.Leerwagen = 0) 
    ) OR
    (-- VBH
    	(l.[letzte Lesestelle] IN (237)) AND (l.Leerwagen = 0) AND (Sektor = 4)
    ) OR
    (-- Pulverkabine 1..2
    	(l.[letzte Lesestelle] IN (603, 703)) AND (l.Leerwagen = 0)
    ) 
    GROUP BY l.Sektor, l.[letzte Lesestelle], l.Leerwagen	
    ORDER BY Position

    Die Funktion dbo.fn_Get_LWDaten_Archiv_TimeExtract liefert alle Datensätze im angegebenen Zeitbereich mit allen Spalten aus der Tabelle [dbo].[TBL_LWDaten_ARCHIV].

    Das Ergebnis sieht wie folgt aus:
    01. Aufgabe 1 3
    02. Aufgabe 2 4
    03. Aufgabe 3 2
    04. Aufgabe 4 5
    07. Pulverkabine 1 3
    08. Pulverkabine 2 5

    Ich möchte allerdings folgendes erreichen:
    01. Aufgabe 1 3
    02. Aufgabe 2 4
    03. Aufgabe 3 2
    04. Aufgabe 4 5
    05. Strahlanlage 0
    06. Vorbehandlung 0

    07. Pulverkabine 1 3
    08. Pulverkabine 2 5

    Meine Überlegungen mit Hilfe eines JOIN einfach das Feld [letzte Lesestelle] aus der Tabelle [dbo].[TBL_LWDaten_ARCHIV]. hinzuzufügen führt zwar zu den gewünschten 0-Zeilen, allerdings auch zu falschen COUNT-Werten in den restlichen Zeilen.
    Hat jemand eine Idee wie man das richtig anstellt?

  • #2
    hallo,
    das sieht mir danach aus als würde deine Funktion bereits die Zeilen mit 0-Werten nicht liefern. Dort evtl. mal die Joins prüfen und INNER JOINs in RIGHT oder LEFT umschreiben damit du auch die nicht übereinstimmenden Zeilen angezeigt bekommst.

    Zusätzlich dazu, wobei aber auch hier deine 0er Zeilen angezeigt werden müssen, hast du die Möglichkeit die Count-Spalte mit einem Subselect zu machen, die entsprechenden Werte die er zählen soll müssen von deinem äußeren SQL mit in das Subselect übergeben werden.

    Wenn ich mich nicht irre kann man ein Subselect aber stets über ein Join auflösen. Würde heißen dass es mit dem erstgenannten Ansatz funktionieren müsste. Evtl. mal mit Count(distinct ...) probieren.

    Comment


    • #3
      stimme openshinok zu. left (outer) oder right (outer) joins würden dir bei diesem problem weiterhelfen, meiner meinung nach.

      Comment


      • #4
        Hallo openshinok!

        Vielen Dank für Deine Antwort. Die Funktion dbo.fn_Get_LWDaten_Archiv_TimeExtract liefert alle Spalten im vorgegebenen Zeitraum zurück. Das Problem ist demnach, dass es im angegebenen Zeitraum keine Zeilen gibt, die dem Kriterium
        Code:
        (-- Strahlanlage
        	(l.[letzte Lesestelle] IN (219)) AND (l.Leerwagen = 0) 
        ) OR
        (-- VBH
        	(l.[letzte Lesestelle] IN (237)) AND (l.Leerwagen = 0) AND (Sektor = 4)
        )
        entsprechen.
        Bislang verwende ich gar keinen JOIN.

        Hast Du einen konkreten Vorschlag, wie meine Abfrage mit JOIN aussehen sollte bzw. könnte, den ich testen kann?

        Vielen Dank für die Hinweise....

        Comment


        • #5
          hallo,
          also ich mache es bei einer Provisionsauswertung auch so dass ich mit 0-Werten auffülle weil ich mir nicht anders zu helfen wusste.

          D.h. normales Select das deine Daten liefert und dann ein weiteres

          Normales Select in #tempTable

          -- auffüllen mit 0-Werten wo die Zeilen fehlen
          INSERT into #tempTable
          SELECT ... FROM tabelle_mit_allen_möglichen_Spalten WHERE Primärschlüsselfeld oder anderes eindeutiges Feld NOT IN (
          SELECT Primärschlüsselfeld oder anderes eindeutiges Feld FROM #tempTable

          )


          Also Daten auffüllen mit 0-Werten die noch nicht in der ersten Abfrage waren.



          Alternativ in deiner Funktion mit einem UNION die fehlenden Werte über ein zweites Select hinzufügen

          Comment


          • #6
            hier ein join bsp:
            http://www.devguru.com/technologies/t-sql/7115.asp

            Comment


            • #7
              Hallo,
              Originally posted by openshinok View Post
              ...Dort evtl. mal die Joins prüfen und INNER JOINs in RIGHT oder LEFT umschreiben damit du auch die nicht übereinstimmenden Zeilen angezeigt bekommst.
              Originally posted by Daman View Post
              ...stimme openshinok zu. left (outer) oder right (outer) joins würden dir bei diesem problem weiterhelfen, ...
              Habt ihr euch mal seine Beispieldaten und seine bisherige Abfrage angesehen? Offensichtlich nicht, sonst hättet ihr gemerkt:
              Originally posted by Hilmar Sackmann View Post
              ...Bislang verwende ich gar keinen JOIN.
              Weil es eine simple Abfrage auf EINE Tabelle ist und da kann man nicht wirklich vernünftig einen Join verwenden. Und die Möglichkeit per Subselect die Counts zu ermitteln scheidet auch aus, weil es die Daten die er mit 0 anzeigen möchte nämlich gar nicht gibt!

              @Hilmar Sackmann:
              Du mußt dir zuerst eine Basis (z.B. durch Anlegen einer entsprechenden Tabelle) schaffen, in der ALLE möglichen Ausgabenamen aufgeführt sind. Wenn du dort ordentliche Relationen zu deinen "letzte Lesestelle" verwendest, dann kannst du einen passenden OUTER JOIN verwenden, bekommst deine 0-Anzeigen und sparst dir obendrein die üblen Case-Konstrukte für die Namensbildung.

              Gruß Falk
              Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

              Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

              Comment


              • #8
                Originally posted by Falk Prüfer View Post
                Habt ihr euch mal seine Beispieldaten und seine bisherige Abfrage angesehen? Offensichtlich nicht, sonst hättet ihr gemerkt:
                Angeschaut, ja aber nicht gecheckt dass er die Funktion ausschließlich auf eine Tabelle anwendet. Aber du hast natürlich recht er braucht irgendwoher die Info was eine vollständige Aufgabe ist.

                Comment


                • #9
                  Hallo Falk!

                  Vielen Dank für Deinen Tip!

                  Habe das ganze wie folgt umgesetzt:
                  Zunächst eine neue Tabelle, in der alle Lestestellen mit "Prosatext" stehen:
                  Code:
                  CREATE TABLE [dbo].[TBL_PARA_Statistik](
                  	[Id] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
                  	[letzte Lesestelle] [int] NOT NULL,
                  	[Position] [nvarchar](50) NOT NULL
                  ) ON [PRIMARY]
                  Dann die angepasste Abfrage:
                  Code:
                  SELECT top 100 PERCENT 
                  s.Position
                  , COUNT(l.[letzte Lesestelle]) AS [Anz LW] 
                  FROM 
                  -- Auswertungszeitraum vorgeben
                  dbo.fn_Get_LWDaten_Archiv_TimeExtract ('18.11.2010', '00:00:00', '19.11.2010', '23:59:59') AS l
                  FULL OUTER JOIN dbo.TBL_PARA_Statistik s ON l.[letzte Lesestelle] = s.[letzte Lesestelle]
                  GROUP BY s.Position, l.[letzte Lesestelle], l.Leerwagen, l.Sektor 
                  -- nur bestimmte Sektoren anzeigen
                  HAVING 
                  (-- Aufhängestation 1..4
                  	l.[letzte Lesestelle] IN (112, 120, 148, 156)
                  ) OR
                  (-- Strahlanlage
                  	l.[letzte Lesestelle] IN (219)
                  ) OR
                  (-- VBH
                  	(l.[letzte Lesestelle] IN (237)) AND (l.Sektor = 4)
                  ) OR
                  (-- Pulverkabine 1..2
                  	(l.[letzte Lesestelle] IN (603, 703))
                  ) 
                  ORDER BY Position  asc
                  Leider hat das keinen Erfolg gehabt. Das Statement unterschlägt immer noch die Zeilen, wo keine Datensätze in der Ursprungs-Tabelle gefunden wurden.

                  Wo mache ich was falsch? Bin wie immer offen für jede Anregung...
                  Vielen Dank im Vorraus!

                  Comment


                  • #10
                    warum HAVING, der ganze Kram gehört ins WHERE...
                    [HIGHLIGHT="SQL"]SELECT s.Position
                    , COUNT(l.[letzte Lesestelle]) AS [Anz LW]
                    FROM dbo.fn_Get_LWDaten_Archiv_TimeExtract ('18.11.2010', '00:00:00', '19.11.2010', '23:59:59') AS l
                    LEFT JOIN dbo.TBL_PARA_Statistik s ON l.[letzte Lesestelle] = s.[letzte Lesestelle]
                    WHERE l.[letzte Lesestelle] IN (112, 120, 148, 156) -- Aufhängestation 1..4
                    OR l.[letzte Lesestelle] IN (219) -- Strahlanlage
                    OR ( l.[letzte Lesestelle] IN (237) -- VBH
                    AND l.Sektor = 4 )
                    OR l.[letzte Lesestelle] IN (603, 703) -- Pulverkabine 1..2
                    GROUP BY s.Position, l.[letzte Lesestelle]
                    ORDER BY s.Position asc[/HIGHLIGHT]

                    Comment


                    • #11
                      Originally posted by ebis View Post
                      warum HAVING, der ganze Kram gehört ins WHERE...
                      Und für den geforderten Fall gehört er sogar in die JOIN-Bedingung. Und wenn dann aus dem LEFT noch ein RIGHT JOIN wird, dann sollte auch das gewünschte Ergebnis rauskommen.

                      Gruß Falk
                      Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

                      Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

                      Comment


                      • #12
                        Danke Euch allen!!!

                        Jetzt funktioniert es so wie gewünscht...

                        Hier die Lösung für alle, die es interessiert....
                        Code:
                        SELECT top 100 PERCENT 
                        s.Position
                        , COUNT(l.[letzte Lesestelle]) AS [Anz LW] 
                        -- Auswertungszeitraum vorgeben
                        FROM dbo.fn_Get_LWDaten_Archiv_TimeExtract ('18.11.2010', '00:00:00', '19.11.2010', '23:59:59') AS l
                        RIGHT JOIN dbo.TBL_PARA_Statistik s ON l.[letzte Lesestelle] = s.[letzte Lesestelle]
                        AND (l.Leerwagen = 0) AND 
                        (
                        	(-- Aufhängestation 1..4
                        		l.[letzte Lesestelle] IN (112, 120, 148, 156)
                        	) OR
                        	(-- Strahlanlage
                        		l.[letzte Lesestelle] IN (219)
                        	) OR
                        	(-- VBH
                        		(l.[letzte Lesestelle] IN (237)) AND (l.Sektor = 4)
                        	) OR
                        	(-- Pulverkabine 1..2
                        		(l.[letzte Lesestelle] IN (603, 703))
                        	) 
                        )
                        GROUP BY s.Position, l.[letzte Lesestelle], s.[letzte Lesestelle]

                        Comment

                        Working...
                        X