Bei SQL SELECT mehrere ID Werte einer Spalte ausschließen?

5 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Mehrere Ansätze (zum Teil aber in einigen DBMS nicht verfügbar; daher Standard-SQL)

1. Table-Join

Da du ein Statement absetzt, kannst du einen Table-Join nehmen. (Besser wären SP. = sicherer, schneller, einfacher zu pflegen) 

Falls du die Tabellen bearbeiten kannst, ist "flaggen" (bit-flag, timestamp, rowversion, etc.) auch ein gutes Mittel, um noch performanter zu werden.

2. IN & BETWEEN

Der Operator IN gestattet dir nicht zusammenhängende Bereiche zu deklarieren.

Der Operator BETWEEN legt zusammenhängende Bereiche fest, lässt sich aber koppeln, also mit "OR" verlängern, um weitere zusammenhängende Bereiche festzulegen.

Beispiele:

Inklusion

... WHERE id IN (0, 1, 2, 3, 22)

... WHERE id BETWEEN 0 AND 3 OR id = 22

Exklusion (= deine Anforderung)

... WHERE id NOT IN (0, 1, 2, 3, 22)

... WHERE id NOT BETWEEN 0 AND 3 AND id <> 22

-----------------------

Wenn du wählen kannst, nimm Ansatz (1) mit den SP. Er ist sicherer, schneller & pflegeleichter. Und er erzeugt weniger Traffic.


RakonDark  04.08.2015, 22:58

bein IN werden die werte auf eine anzahl begrenzt , es gehen halt nicht sehr viele ich glaub es waren 256

Unsinkable2  05.08.2015, 17:56
@RakonDark

Du kannst das mit Verkettungen lösen:

WHERE id IN (1, ..., x) OR id IN (999, ...., y) OR id IN (9,999, ...., z)

Hello there,

eine zweite Tabelle ist hier nicht nötig.

Wenn es mehrere Werte sein können, machst du es folgendermaßen:

SELECT * FROM user_data
WHERE ID NOT IN(1, 4, 6, 3);

Hast du das Ganze vielleicht dynamisch als Array in PHP, dann kannst du diese Zahlen auch einfügen in das Statement:

$sql = "SELECT * FROM user_data
WHERE ID NOT IN ( " . implode(',', $werte) . ");";

Hoffe ich konnte dir helfen.

MfG

Alex



RakonDark  04.05.2018, 18:45

Nur ums mal Up To Date zu halten. Ich hab nach geguckt und man kann den chache dafür bestimmen . Es geht also , wenn man will , in ganz andere dimensionen ;)

RakonDark  04.08.2015, 22:57

dazu sollte man sagen das SQL die Anzahl auf 256 werte begrenzt .

wotan38  30.08.2015, 10:02
@RakonDark

Bei meiner Datenbank (IBM DB2) habe ich bisher noch keine Begrenzung festgestellen können, obwohl ich z.T. sehr große Datenmengen in den Subselect bekomme. Möglicherweise sind die (einstellbaren) Grenzwerte in der Konfiguration so hoch eingestellt. 

wotan38  30.08.2015, 10:14
@Alextoexplain

Wo siehst Du da ein Designproblem? Würde mich interessieren, da ich öfter einen solchen Subselect benutze und auch nicht wüsste, wie man das sonst machen sollte. Ich habe eine sehr komplexe Datenbankanwendung (57 Tabellen). Ich schätze Deine Ratschläge und habe schon öfter gute Tipps Deinen Antworten entnehmen können.

Alextoexplain  30.08.2015, 12:33
@wotan38

Nein ich meinte, wenn jemand eine WHERE-Bedingung hat mit einem IN oder NOT IN Teil, der 256 Elemente fasst gegen die geprüft werden soll, so wie Rakon eben meint. Das wäre definitiv schlecht designt wenn man solche Vorgehensweise benötigen würde.
Danke für deine netten Worte übrigens *-* Hab ich eigentlich schon ein Kompliment von dir? :P

Alextoexplain  30.08.2015, 12:34
@wotan38

Und das nennst du sehr komplex? Ich arbeite in einer Softwarefirma im Support, und unsere Anwendung hat derzeit 575 Tabellen. OK die Datenbank hat auch Null Designkonzept, aber trotzdem^^

Generell zur Vermeidung von doppelten Werten im Select: 

SELECT DISTINCT <Spalte> FROM <Table>

Zum Ausschluss von Werten die in Tabelle B bereits stehen: 

SELECT ID FROM TabelleA WHERE ID NOT IN (SELECT ID FROM TabelleB)


RakonDark  04.08.2015, 22:58

auch hier ist eine begrenzung bei IN der anzahl der werte

wotan38  22.04.2018, 20:44
@RakonDark

Bei meiner Datenbank (IBM DB2) gibt es keine Begrenzung bei IN, jedenfalls nicht im Bereich um die 100000.

Habe es gerade ausprobiert: mit 132712 hat es noch funktioniert.

Irgendwo gibt es natürlich eine Grenze.

RakonDark  04.05.2018, 18:43
@wotan38

praktisch kannst du den cache für den IN setzten wie du willst :) theortisch guckt man sich aber die performance an . gehen tut es jedenfalls .

Hallo,

ich weiß nicht, mit welchem DBMS du arbeitest, aber im Wesentlichen sollte sich nachfolgender Hinweis gleichen. Ich würde bei derartigen Angelegenheiten mit Timestamp arbeiten. Vielleicht hilft folgende Seite auf adäquate Lösungen (eine Lösung für gelöschte Objekte müsste auch noch erstellt werden;): https://msdn.microsoft.com/en-us/library/cc305973(v=sql.110).aspx


Regenwurm97 
Beitragsersteller
 02.08.2015, 15:05

Danke genau nach sowas habe ich gesucht! :)

WHERE ID NOT BETWEEN -1 AND 4


wotan38  03.08.2015, 09:57

Anmerkung: Der BETWEEN schließt die angegebenen Grenzwerte ein. Beim Bezug auf das Beispiel in der Frage müsste es heißen BETWEEN 0 AND 3. Bei meiner Datenbank ist das jedenfalls so.

EightSix  03.08.2015, 10:44
@wotan38

War mir da nicht mehr so sicher - kann aber gut sein :). Danke

Regenwurm97 
Beitragsersteller
 02.08.2015, 14:29

Ja mist das Beispiel ist blöd. Es könnte gut sein, dass die Nummern nicht aufeinander folgen. Also ich will 1,4,6,3 ausschließen. Muss ich dann für jede Nummer einzeln prüfen
(Also WHERE ID != 1 AND ID != 4 AND ...)?

EightSix  02.08.2015, 14:43
@Regenwurm97

Es ginge über eine zweite Tabelle in die zuerst deine bereits abgerufenen IDs reinschreibst.Aber eine bessere, und gängigere Methode wäre es, ein zusätzliches Feld einfügen in dem der Zeitpunkt der letzten Aktualisierung des jeweiligen Datensatzes speicherst (LastChanged). Beim Abrufen der Daten speicherst du den Zeitpunkt des Abrufes. Beim nächsten Abruf fragst nur Datensätze ab die danach aktualisiert wurden. Es empfiehlt sich, den Zeitpunkt in UTC Zeitzone umzuwandeln um Konflikte zwischen Server- und Clientzeit zu vermeiden.

Regenwurm97 
Beitragsersteller
 02.08.2015, 15:05
@EightSix

Ah das klingt nach einer echt guten Lösung! Danke, genau das habe ich gesucht! :)