sql: abfrage negieren?



  • hallo!

    meine tabelle 'artikel' sieht etwa so aus:

    artNr| ..
    -----|----
    123 
    456
    789
    111
    222
    

    folgendes statement gibt 2 datensätze zurück:

    SELECT `artNr` FROM artikel WHERE `artNr` IN (123,111)
    

    ich will allerdings genau alle anderen bekommen!

    sowas wie:

    SELECT `artNr` FROM artikel WHERE `artNr` [b]NOT[/b] IN (123,111)
    

    .. funktioniert leider nicht, weil das NOT logisch interpretiert wird - am ende kommt nur müll raus.

    ich kann leider kein:

    SELECT `artNr`FROM artikel WHERE `artNr` != "123" AND `artNr` != "111"
    

    benutzen, da es nicht schnell genug ist (in echt habe ich > 100000 abfragen). select braucht da ewigkeiten für!

    frage nun also:
    wie kann ich das ergebnis des SQL IN()s negieren?

    besten dank und schöne grüße:)



  • ok ich muss mich korrigieren.. ein IN() liefert nur 1, 0 oder null wieder. kann ich also vergessen - mein test hatte einen fehler, sorry.

    mein problem besteht jedoch immernoch. ich brauche eine effiziente lösung für viele select-statements.

    als beispiel mit nur 2645 ids in $ids:

    $s_time = strtok(microtime(), " ") + strtok(" ");
    
    	$id_array = split(',', $ids);
    
    	for($n = 0; $n < sizeof($id_array); $n++) {
    		$query = 'SELECT `artNr` FROM artikel WHERE `artNr` = '.$id_array[$n];
    
    		$res = mysql_query($query);
    
    		if(mysql_num_rows($res) >= 1)
    			$mysql_count++;
    	}
    
    	$e_time = strtok(microtime(), " ") + strtok(" ");
    
    	echo "Dauer: ".number_format($e_time - $s_time, 6)." Sekunden<br>";
    
    // Dauer: 327.262672 Sekunden
    

    das sind über 5 minuten, dauert viel zu lange. habe max_execution_time etc schon hoch gesetzt, is ja aber auch keine lösung!

    kann man das performanter machen?
    beste grüße



  • Wieso machst Du das nicht so?

    SELECT `artNr` FROM artikel WHERE `artNr` = $id[0] OR `artNr` = $id[1] OR ...
    
    $sql='SELECT `artNr` FROM artikel WHERE';
    for($i=0; $i<count($id_array); ++$i)
    {
      $sql.=' `artNr` = '.$id_array[$i];
      if($i<count($id_array)-1)
        $sql.=' OR';
    }
    
    $query=mysql_query($sql);
    while(false!==($result=mysql_fetch_array($query)))
    {
      // tue irgendwas, z.B. artNr ausgeben:
      print($result['artNr'].'<br />');
    }
    

    /EDIT: Wieso sollte artNR NOT IN (111, 222) nicht funktionieren? http://dev.mysql.com/doc/refman/5.1/de/comparison-operators.html sagt, dass es geht und hab es gerade mal selber ausprobiert, damit lassen sich toll die Dinger ausschließen.



  • Schon mal an einen JOIN gedacht?
    Oder daran evtl. ein Feld in die Tabelle aufzunehmen, was sich da missbrauchen lässt für?



  • Hi perfo, welche Datenbank nutzt du? Ich verwende "NOT IN" regelmäßig unter PostgreSQL und dort funktioniert es wunderbar.



  • Zeigst Du uns bitte mal ein minimales Schema samt funktionierender SQL-Abfrage und EXPLAIN-Output? Danke.



  • entschuldigt bitte das späte antworten!
    ich habe mich jetzt für eine lösung mit 'on duplicate key update' entschieden.. ich hatte ein paar logik-fehler in meinem alten ansatz. dieser weg hier erscheint mir nun weit aus besser und perfomanter:)

    vielen dank für eure mühe und schöne grüße!



  • problem ist ja gelöst und ich bin kein sql experte aber ich denke es hätte auch einfach mit einem verschachtelten select a la select where id != (select ...) oder so etwas in der richtung funktioniert.



  • Er.
    Wenn "a NOT IN (...)" nicht geht, wieso dann nicht "NOT (a IN (...))"? 🙂
    (Und "a NOT IN (...)" geht mit MS-SQL auch wunderbar, schreib ich immer so)


Anmelden zum Antworten