2 Stimmen

Wähle zwei Zeilen in einem einzelnen SQL-Statement nur, wenn beide Bedingungen erfüllt sind.

Ich habe eine Tabelle mit den folgenden Daten.

Tabellenname: myTable

prodID   catNo   variable1  variable2
1        20      Cat        Blue
2        10      Cat        Rot
2        15      Cat        Grün
2        20      Cat        Schwarz
3        20      Cat        Gelb
4        10      Cat        Orange
4        15      Cat        Braun
4        20      Cat        Schwarz
5        30      Cat        Pink

Ich möchte alle Spalten aus meiner Tabelle auswählen, bei denen Folgendes zutrifft
"(prodID = 2 und catNo = 10) UND (prodID = 2 und catNo = 15)". Dies bedeutet, dass nur die beiden Zeilen zurückgegeben werden sollen, wenn beide Bedingungen erfüllt sind und es wird nichts zurückgegeben, wenn beide Zeilen nicht vorhanden sind. Also wird meine Ergebnistabelle so aussehen.

Tabellenname: results

prodID   catNo   variable1  variable2
2        10      Cat        Rot
2        15      Cat        Grün

Ich habe versucht, bedingte if-Anweisungen zu verwenden, aber ich kann sie nicht im SQL zum Laufen bringen. Meine aktuelle Lösung besteht darin, alle Zeilen mit prodID = 2 zurückzubekommen und dann mit PHP die if-Anweisung zu verwenden, um zu entscheiden, was angezeigt werden soll. Dies funktioniert jedoch nicht mit der paginierten Ergebnisanzeige, die ich entworfen habe, da mein Limit die Anzahl der Ergebnisse pro Seite verfälschen wird. Ich weiß, dass ich 'HAVING COUNT rows = 2' verwenden könnte, aber ich bin mir nicht sicher, wie ich es formulieren soll.

0voto

Fi Horan Punkte 466

Danke M Khalid Junaid's Antwort funktioniert. Ich habe es geschafft, eine Lösung zu finden, die keinen Join erfordert, was bei einer sehr großen Tabelle wie meiner eher langsam wäre:

select * 
from myTable 
where ((prodID = 2 and catNo = 10) or (prodID = 2 and catNo = 15)) 
group by catNo
having (
        select count(distinct(catNo))
        from myTable 
        where ((prodID = 2 and catNo = 10) or (prodID = 2 and catNo = 15))
)=2;

0voto

GruzzGruzz Punkte 1

Die meisten geposteten Lösungen fehlen der Teil über die Rückgabe von nichts, es sei denn, BEIDE WHERE-Bedingungen sind erfüllt. Daher wird die Mehrheit der Lösungen versagen, wenn nur eine Bedingung erfüllt ist, da sie immer noch eine Zeile zurückgeben wird, anstatt keine.

Angenommen, Sie möchten in der Lage sein, nach beliebig vielen WHERE-Bedingungen zu suchen, und nicht nur nach zwei, könnten Sie eine Lösung mit einer Unterabfrage verwenden.

Mit diesem Ansatz können Sie die Anzahl der qualifizierten Zeilen im Ergebnisset vor der Ausgabe überprüfen. Es gibt einige Möglichkeiten, dies zu tun, aber die Idee ist, die Anzahl der qualifizierten Zeilen mit Ihrer erwarteten Anzahl von Zeilen zu vergleichen. Wenn sie übereinstimmen, geben Sie die Zeilen aus. Wenn sie nicht übereinstimmen, geben Sie ein leeres Ergebnis zurück.

M Khalid Junaid hat eine Lösung gepostet, die eine Gruppierung mit einer HAVING-Bedingung in einer Unterabfrage verwendet, um zu überprüfen, dass die Größe des Ergebnissets 2 beträgt. Diese Lösung funktioniert für Ihr spezifisches Beispiel und ähnliche Fälle. Es könnte jedoch nicht funktionieren, wenn Ihre WHERE-Bedingungen komplexer oder vielfältiger werden, da sie darauf beruht, dass ProdID in jeder WHERE-Bedingung gleich ist, aber das Prinzip ist korrekt. Außerdem erfordert diese Methode, dass die WHERE-Bedingung zweimal gegen die Quellentabelle verarbeitet wird, während die unten stehende Methode dies nur einmal tut. Für sehr große Tabellen und/oder viele WHERE-Bedingungen sollte diese Methode effizienter sein.

Sie können Unterabfragen entweder direkt in der FROM-Bedingung wie in anderen Beispielen oder über WITH-Anweisungen konstruieren. Ich habe hier letzteres verwendet, da es klarer zeigt, was passiert:

Mit ResultSet as (select * from myTable
        where (prodID = 2 AND catNo = 10) OR (prodID = 2 AND catNo = 15)), -- Ihre WHERE-Bedingung
    TotalRows as (select COUNT(*) as TRows from ResultSet) -- Anzahl der Ergebnisse
select ResultSet.*
from ResultSet
    inner join TotalRows on 1=1 -- Erzwingen des Joins, unabhängig davon, was in den Tabellen enthalten ist
where TRows = 2 -- hier überprüfen Sie, wie viele Ergebniszeilen Sie erwarten

Die "ResultSet" ist die Unterabfrage, in der Ihre WHERE-Klausel steht, und sie kann so einfach oder komplex sein, wie Sie möchten. "TotalRows" zählt das Ergebnisset und enthält daher nur eine Zeile. Dann verknüpfen Sie die Unterabfragen miteinander, geben jedoch nur Zeilen aus der ersten aus, wenn die Anzahl der Ergebniszeilen (TRows) mit der von der letzten erwarteten Zeilenanzahl übereinstimmt.

0voto

Szymon Roziewski Punkte 926

Sie können versuchen, eine Funktion zu schreiben. Es ist ziemlich lang, aber ziemlich einfach zu verstehen

DROP FUNCTION getIt();
CREATE OR REPLACE FUNCTION getIt()
RETURNS TABLE (prodID INTEGER, catNo INTEGER, variable1 TEXT, variable2 TEXT) AS
$BODY$
BEGIN
  IF (CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=2 and "catNo" = 10) AS INTEGER)>0 AND CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=2 and "catNo" = 15) AS INTEGER)>0)
  THEN RETURN QUERY SELECT * 
     FROM "myTable" 
     where "prodID"=2 and ("catNo" = 10 or "catNo" = 15 );
  END IF;
END;
$BODY$ 
LANGUAGE 'plpgsql';
SELECT * FROM getIt();

Es kann parametrisiert werden

DROP FUNCTION getIt(pid integer, cid1 integer, cid2 integer);
CREATE OR REPLACE FUNCTION getIt(pid integer, cid1 integer, cid2 integer)
RETURNS TABLE (prodID INTEGER, catNo INTEGER, variable1 TEXT, variable2 TEXT) AS
$BODY$
BEGIN
  IF (CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=$1 and "catNo" = $2) AS INTEGER)>0 AND CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=$1 and "catNo" = $3) AS INTEGER)>0)
  THEN RETURN QUERY SELECT * 
     FROM "myTable" 
     where "prodID"=$1 and ("catNo" = $2 or "catNo" = $3 );
  END IF;
END;
$BODY$ 
LANGUAGE 'plpgsql';
SELECT * FROM getIt(2, 10, 15);

-2voto

tjibbe chris Punkte 160

Die Bedingung sollte (prodID = 2 und catNo = 10) ODER (prodID = 2 und catNo = 15) sein

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X