SQL-Query für MS-SQL-Server mit Distinct und count



  • Ich habe folgende Query:

    Select count(*) as ANZAHL from [dbo].[TRWErgebnisse] where " + Bedingung;
    

    Nun möchte ich doppelte MotorNummern der Spalte MotorNummer rauswerfen, so dass ich jede Motornummer nur einmal zähle. Wie kann ich in dieser Query counten um mit Distinct auf mein richtiges Ergebnis zu kommen.
    Danke schon im Voraus



  • Meinst du soetwas ?

    SELECT COUNT(DISTINCT MotorNummer) FROM ..
    

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_ca-co_5790.asp



  • das ist genau das was ich gesucht hab glaub ich. Ich werd es morgen bei der arbeit gleich mal ausprobieren, sieht aber genau danach aus. vielen Dank



  • 😃 👍 Genau das ist es !

    Select count(DISTINCT MotorNummer) as ANZAHL from[dbo].[TRWErgebnisse] where " + Bedingung
    

    Also genau das was du gesagt hast Tip Top!!!!!
    Vielen Dank



  • AAhHH Stop ich bracuh in der Query noch was. Bzw. welche wirft er jetzt raus bei den doppelten? Ich brauch immer den mit dem neusten Zeitstempel von den doppelten!! Sowas wie reverse find! die aktuellsten Timestamps stehen am Ende. Mit was ich noch Probleme hab bedarf vielleicht erst einmal einer kleinen Erklärung. In der Abfrage will ich wissen wieviele Motoren getestet wurden, da ein Motor mehrmal getestet werden kann muss ich die doppelten raus schmeißen. (ist ja nun erledigt) jetzt will ich wissen wieviele diese Motoren denn immer noch IO oder immernoch NIO sind. Wenn ich die Anfrage so mach:

    Select count(DISTINCT MotorNummer) as ANZAHL from[dbo].[TRWErgebnisse] where ID <= 500  AND [ErrCode] = 0 AND MotorGut = 1
    

    dann schmeißt er ja zuerst mal die mit nem Errorcode bzw MotorGut = 0 weg.
    Wenn ich danach die invertierte Abfrage mache also

    ... AND ([ErrCode] = 1 OR MotorGut = 0)
    

    kann ich ja nicht garantieren dass in diesen Ergebnissen nicht ein Motor aus der IO Abfrage mit drin ist. so komm ich in Summer von IO und NIO immer auf mehr wie die Gesamtstückzahl! Wie filtere ich die "Grenzgänger" also die die mal NIO waren jetzt aber IO sind?
    Kann man das verstehen was ich geschrieben hab??

    //EDIT: wenn ich order by ZeitStempel asc mach, sortiert er dann erst wenn er schon selected hat oder sortiert er erst und selected dann? Vermutlich nicht oder?



  • AAAAlso jetzt hab ich was gebastelt, vielleicht kann mir da jemand helfen: Ich hab folgendes!

    SELECT COUNT(*) AS ANZAHL FROM (SELECT MAX(CONVERT(integer, [ZeitStempel])) AS LetzterTest, MotorNummer FROM [dbo].[TRWErgebnisse] WHERE MotorGut = 1 AND ErrCode = 0 GROUP BY [MotorNummer])
    

    Jetzt sagt mir mein VC++ Prog wenn ich das senden will

    ---------------------------
    ACRSQL
    ---------------------------
    Zeile 1: Falsche Syntax in der Nähe von ')'.
    Anweisung(en) konnte(n) nicht vorbereitet werden.

    ---------------------------
    OK
    ---------------------------

    Was ist falsch?



    1. Willst du jetzt doch COUNT(*) oder count(DISTINCT MotorNummer) ?
    2. Du hast kein [dbo].[TRWErgebnisse] where drin.


  • Was ist falsch?

    1. Auf isabeau hören 😃
    2. Ich glaube soetwas funktioniert nicht:

    SELECT COUNT(*) AS ANZAHL FROM ( ..

    Ich hab's gestern ausprobiert. Hat nicht geklappt 😕 Es muss SELECT .. FROM table sein.

    EDIT: du hast SELECT COUNT(*) FROM Unterabfrage ⚠



  • jaja also ich will eigentlich schon count(DISTINCT MotorNummer) aber ich will in der Suche ne untersuche wo ich IO und NIO counte! das aber nur wenn gleiche Motornummer die mit dem höchsten Zeitstempel.

    Kann man das verstehen?
    Formulier es mal mündlich

    Select alles was ich brauch zähle Motornummern schmeiß aber doppelte Motornummern raus achte aber darauf dass der letzte Zeitstempel unter den gleichen Motoren drin bleibt (das ist jetzt die Gesamtanzahl der Motoren) in dieser Suche gib mir die Anzahl an Motoren die gut getestet wurden

    //EDIT: was ich noch sagen wollte, doch doch folgendes geht!

    Select count(*) as ANZAHL from [dbo].[TRWErgebnisse] where
    


  • OK. Beispiel:

    CREATE TABLE test(id INT PRIMARY KEY, m_nr INT, time_key INT, flag INT);
    
    INSERT INTO  test VALUES(1, 100, 1, 0);
    INSERT INTO  test VALUES(2, 200, 2, 1);
    INSERT INTO  test VALUES(3, 200, 3, 1);
    INSERT INTO  test VALUES(4, 100, 4, 0);
    INSERT INTO  test VALUES(5, 100, 5, 1);
    
    SELECT COUNT(*) AS anzahl, m_nr, id 
    FROM test
    WHERE time_key IN ( SELECT MAX(time_key) FROM test WHERE flag = 1 GROUP BY m_nr)
    GROUP BY m_nr, id; 
    
    -- oder
    
    -- Anzahl der guten Motoren
    SELECT COUNT(*) AS anzahl FROM test
    WHERE time_key IN ( SELECT MAX(time_key) FROM test WHERE flag = 1 GROUP BY m_nr);
    

    Ist jetzt keine Lösung, mehr als Anregung ..



  • Das sieht ja schon mal nicht schlecht aus, mit dem bin ich auch schon ein ganzes Stück weiter gekommen, aber leider ist das noch nicht 100% das was ich wollte. Also es geht:

    SELECT count(Distinct MotorNummer) AS ANZAHL 
    FROM [dbo].[TRWErgebnisse] 
    WHERE Zeitstempel IN ( SELECT MAX(Zeitstempel) 
                           FROM [dbo].[TRWErgebnisse] GROUP BY MotorNummer) 
    AND ID<=23 AND [ErrCode] = 0 AND MotorGut = 1
    

    Auch wenn ich nach dem Schema alle oder NIOs abfrage. Jetzt aber das Problem:
    Wenn ich folgende Tabelle habe:

    ID    MotorNummer    GUT
    1     4711            NIO
    2     0812            NIO
    3     0813            IO
    4     0815            IO
    5     0815            IO
    6     0815            NIO
    

    Und ich mach jetzt obigen code dann zählt er die IOs das wäre dann 2 IO
    Wenn ich die query invertiere zählt er 3 NIO
    Wenn ich due Gut-Abfrage weglasse dann zählt er 4. Ist ja alles einzeln richtig, aber wenn ich obige Tabelle habe sollten es eigentlich ein IO und 3 NIO sein. Weil der Motor 0815 ja schon NIO gecountet wurde. Aber die Abfragen wissen ja gar nichts von einander, wie sollen sie dann auch checken ob die andere schon was hat. Kann es sein dass folgender Part aus der Query nicht richtig funktioniert?

    Zeitstempel IN ( SELECT MAX(Zeitstempel) FROM [dbo].[TRWErgebnisse] GROUP BY MotorNummer)
    

    Weil wenn ich das richtig verstanden habe sollte er ja nur die neuesten nehmen, dann sähe ja die Tabelle so aus:

    ID    MotorNummer    GUT
    1     4711            NIO    <= NIO
    2     0812            NIO    <= NIO
    3     0813            IO     <= IO
    4     0815            IO     <= raus
    5     0815            IO     <= raus
    6     0815            NIO    <= NIO
    

    Dann würde ja aber auch das counten stimmen. Sieht jemand den Fehler?



  • aber wenn ich obige Tabelle habe sollten es eigentlich ein IO und 3 NIO sein

    Mit dieser Anweisung bekommst du 4 zurück. 3 NIO + 1 IO

    SELECT COUNT(*) AS anzahl FROM test 
    WHERE time_key IN ( SELECT MAX(time_key) FROM test GROUP BY m_nr);
    

    Mir ist jetzt nicht klar, wo das Problem ist 😕

    Aber die Abfragen wissen ja gar nichts von einander, wie sollen sie dann auch checken ob die andere schon was hat.

    ID    MotorNummer TimeStamp     GUT
    1     4711          1           NIO
    2     0812          2           NIO
    3     0813          3           IO
    4     0815          4           IO
    5     0815          5           IO
    6     0815          6           NIO
    
    WHERE time_key IN ( SELECT MAX(time_key) FROM test GROUP BY m_nr
    

    Liefert

    ID    MotorNummer TimeStamp     GUT
    1     4711          1           NIO
    2     0812          2           NIO
    3     0813          3           IO
    6     0815          6           NIO
    

    zurück.

    SELECT COUNT(*) AS anzahl FROM test WHERE
    

    zählt jetzt 4.

    😕 😕



  • Ja, OK mit deinem Post gehe ich konform. Ich bekomme auch 4 zurück.
    Ich will 3 Zahlen haben.
    1. Anzahl Motoren
    2. Anzahl gute Motoren
    3. Anzahl schlechte Motoren.
    Meine Querys dazu sind demnach:

    SELECT count(Distinct MotorNummer) AS ANZAHL FROM [dbo].[TRWErgebnisse] WHERE Zeitstempel IN ( SELECT MAX(Zeitstempel) FROM [dbo].[TRWErgebnisse] GROUP BY MotorNummer) " + Bedingung
    

    Wobei Bedingung für die drei Zahlen für 1. nichts ist, für 2. und 3. folgendes:

    AND [ErrCode] = 0 AND MotorGut = 1 // für 2.
    AND ([ErrCode] != 0 OR MotorGut = 0) //für 3.
    

    wenn ich nun die drei Anfragen mache, kommen gesamt zwar die 4 raus was ja auch richtig ist die zweite Anfrage nach guten liefert aber 2
    und die nicht guten 3 (wären dann aber ja 5)

    Er muss also wenn die doppelten draußen sind dieses Ergebnis nach IO und NIO durchsuchen.

    Nochmal anderes Beispiel ich will IO zählen und hab

    0815 IO
    0815 NIO
    4711 NIO
    4711 IO
    

    Wenn ich jetzt gut suche bleiben IMHO bei der Abfrage von oben

    0815 IO
    4711 IO
    

    hier nimmt er nun die ältesten und zählt die.Da kommt dann zwei raus.
    richtig wäre aber zuerst mal schauen welche der doppelten am ältesten sind also

    0815 NIO
    4711 IO
    

    und erst jetzt dann bei der Gutsuche die nicht guten raus schmeißen! Dann bleibt noch

    4711 IO
    

    wenn ich das nun zähle komme ich auf 1 wenn ich erst NIO wegwerfe komme ich aber auf 2 s.o.
    Vielen Dank für deine Hilfe!



  • CREATE TABLE test(id INT PRIMARY KEY, m_nr INT, time_key INT, flag INT); 
    
    INSERT INTO  test VALUES(1, 0815, 1, 0); 
    INSERT INTO  test VALUES(2, 0815, 2, 1); 
    INSERT INTO  test VALUES(3, 4711, 3, 1); 
    INSERT INTO  test VALUES(4, 4711, 4, 0); 
    
    SELECT m_nr FROM test WHERE time_key IN( 
     SELECT MIN(time_key) AS time_key FROM test 
     WHERE m_nr IN (SELECT m_nr FROM test GROUP BY m_nr HAVING COUNT(*) > 1)
     GROUP BY m_nr) AND flag = 1;
    

    Du brauchst ein anständiges SQL - Buch ⚠ Lass dich nicht von Informix abschrecken. Hier sind die SQL Grundlagen sehr gut erklärt
    http://www.amazon.de/exec/obidos/ASIN/3827312450/qid=1116847129/sr=1-8/ref=sr_1_10_8/028-5141478-6164518

    Ich muss mich jetzt wieder meiner Arbeit widmen.
    Viel Erfolg ..



  • Ich hab einige Datenbankbücher, aber wenn ich so ein Problem hab krieg ich das dennoch nicht hin.
    Eine kleine Frage hab ich noch. Sonst hatte ich immer AS ANZAHL und in Anzahl stand dann mein gezählter Wert. Ich brauche auch jetzt ne Spalte die ANZAHL heißt, aus der ich die Anzahl raus holen kann. Wo steht denn nu die Anzahl drin?
    DANKE viel mals für deine Bemühungen find ich echt klasse, dass du mir so geholfen hast.



  • Ich hab einige Datenbankbücher, aber wenn ich so ein Problem hab krieg ich das dennoch nicht hin.

    Dir fehlt einfach die Erfahrung. Bist du gerade im Praxissemester?

    Ich brauche auch jetzt ne Spalte die ANZAHL heißt, aus der ich die Anzahl raus holen kann. Wo steht denn nu die Anzahl drin?

    Da bin ich jetzt überfragt.

    DANKE viel mals für deine Bemühungen find ich echt klasse, dass du mir so geholfen hast.

    Jo, kein Problem 😉



  • Tanzfreak schrieb:

    Dir fehlt einfach die Erfahrung. Bist du gerade im Praxissemester?

    Jo bin ich. 🙂

    Tanzfreak schrieb:

    Da bin ich jetzt überfragt.

    😮 Du hast doch die Query gebastelt, wo ist das ergebnis dass du erzielen wolltest?



  • Ach so !!

    SELECT COUNT(m_nr) AS anzahl FROM test WHERE time_key IN( 
     SELECT MIN(time_key) AS time_key FROM test 
     WHERE m_nr IN (SELECT m_nr FROM test GROUP BY m_nr HAVING COUNT(*) > 1) 
     GROUP BY m_nr) AND flag = 1;
    


  • also jetzt hab ich ne Lösung wie ich es haben wollte, falls jemand mal in ähnliche Situation gelangt und durch ne Suche hierauf kommt will ich die Lösung nicht vorenthalten. Ich mache es nun so:

    CString CACRSQLSet::CountTeile(CString Bedingung)
    {
    	CString strSQL_gesTeile = STRSQL_TEILE;
    
    	CString SqlCmd1 = "Create table #tmp_Auswertung (Zaehler int, MotorNummer char (10))"; 
    	CString SqlCmd2 = "INSERT INTO #Tmp_Auswertung ( Zaehler, MotorNummer) SELECT Max(dbo.TRWErgebnisse.Zaehler) AS MaxOfZaehler, dbo.TRWErgebnisse.MotorNummer FROM dbo.TRWErgebnisse GROUP BY dbo.TRWErgebnisse.MotorNummer";
    	CString SqlCmd3 = "SELECT Count (*) AS ANZAHL, dbo.TRWErgebnisse.ErrCode FROM dbo.#tmp_Auswertung INNER JOIN dbo.TRWErgebnisse ON dbo.#tmp_Auswertung.Zaehler = dbo.TRWErgebnisse.Zaehler AND dbo.#tmp_Auswertung.MotorNummer = dbo.TRWErgebnisse.MotorNummer AND " + Bedingung + " GROUP BY dbo.TRWErgebnisse.ErrCode asc";
    	CString SqlCmd4 = "Drop table #Tmp_Auswertung";
    	CString strAnzahl;
    	CDatabase db;
    	db.Open( _T("ACR"),FALSE,true,_T("ODBC;UID=anyusr;PWD=anyusr"),false);
    
    	CRecordset Set(&db);
    
    	db.ExecuteSQL(SqlCmd1);
    	db.ExecuteSQL(SqlCmd2);
    	Set.Open(CRecordset::dynaset | CRecordset::forwardOnly, SqlCmd3);
    
    	if(!Set.IsEOF())
    	{
    		Set.GetFieldValue("ANZAHL", strAnzahl);
    	}
    	Set.Close();
    	db.ExecuteSQL(SqlCmd4);
    	return strAnzahl;
    }
    

    Und es geht!!


Log in to reply