2013-06-13 8 views
6

Ich habe zwei Tabellen mit sehr ähnlichen Strukturen.Wählen Sie dieselbe Spalte nur aus mehreren Tabellen WHERE etwas = etwas

Universidades 
nombre | contenido | becas | fotos etc etc etc 
Internados 
nombre | todo | becas | fotos etc etc etc 

Ich möchte eine SQL-Anweisung schreiben, die die nombre von beiden wählen wird und sie als Array zurück, nur wenn es passt. Von dem, was ich gesehen habe UNION SELECT scheint der Weg zu sein, dies zu tun. Ich habe WHERE am Ende hinzugefügt und ich denke, das ist, wo es falsch läuft. Bisher empfange ich die erste Reihe der ersten Tabelle.

Was schreibe ich falsch?

$db = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD); 
$data = $db->prepare("SELECT nombre FROM internados UNION SELECT nombre FROM universidades WHERE nombre = ?"); 
$data->execute(array($nombre)); 

Entschuldigungen, ich will ein Ergebnis aus diesen beiden Tabellen retrive. Namees in der nombre Spalte sind alle individuell und unterschiedlich in beiden Tabellen

+0

Was bedeutet "es als Array nur dann zurückgeben, wenn es übereinstimmt"? – ErikE

+0

Gibt alle Informationen aus dieser Zeile im Array-Format zurück, wenn Nombre gleich dem übergebenen Wert ist –

+0

Was DBMS und Version, bitte? Was bedeutet "Array-Format"? In SQL gibt es Zeilen und Spalten. Das ist es! – ErikE

Antwort

16

Ein Problem, darauf zu hinweisen, bevor wir das Problem lösen, besteht darin, dass jede Abfrage in einem UNION verschieden ist und erfordert eine eigene WHERE Klausel. Die einzige Klausel, die für die UNION als Ganzes gilt, ist ORDER BY. So Ihre Abfrage können wie einige Optimierungen benötigt:

SELECT nombre 
FROM dbo.internados 
WHERE nombre = ? -- the added line 
UNION 
SELECT nombre 
FROM dbo.universidades 
WHERE nombre = ? 
; 

Zweitens, wenn Sie die beiden Tabellen wollen beide die gleiche nombre haben (was nicht ganz klar ist, aber ich vermute, das ist richtig), dann das wird nicht Arbeit, weil es einfach einen nombre zurückgibt, wenn der Wert in entweder Tabelle gefunden wird. Wahrscheinlich der beste Weg, dies zu lösen, ist nur ein tun beitreten:

SELECT I.nombre 
FROM 
    dbo.internados I 
    INNER JOIN dbo.universidades U 
     ON I.nombre = U.nombre 
WHERE 
    I.nombre = ? 
    AND U.nombre = ? -- perhaps not needed, but perhaps helpful 
; 

Ich bin nicht 100% sicher, dass ich verstehe genau, was Sie suchen, bitte sprechen, wenn ich die Marke verpasst haben.

können Sie über JOIN und UNION so denken:

  • JOIN: verbindet Reihen horizontal
    • Spiele sie auf Bedingungen
    • Erstellt neue Spalten
    • Doesn‘ t genau crea te Zeilen, da alle Daten aus vorhandenen Zeilen stammen, aber wird eine Zeile aus einer Eingabe duplizieren, wenn die Bedingungen mit mehreren Zeilen in der anderen Eingabe übereinstimmen. Wenn beide Eingaben Duplikate enthalten, multipliziert sie die Anzahl der Zeilen von einer Eingabe mit der Anzahl der übereinstimmenden Zeilen von der anderen.
    • Wenn es überhaupt keine Übereinstimmungsbedingung gibt (denke CROSS JOIN), dann können Sie ein kartesisches Produkt erhalten, bei dem jede Zeile in einer Eingabe mit jeder Zeile in der anderen übereinstimmt.
    • Wenn ein OUTER join-- LEFT, RIGHT, FULL --wenn Zeilen aus dem inneren Eingang (oder Eingabe entweder mit FULL) kann die andere nicht übereinstimmt, wird NULL s in den Spalten für den anderen Eingang gelegt werden.
  • UNION: Stapel Reihen vertikal
    • Im Allgemeinen schafft neue Reihen
    • keine Bedingungen verwendet werden, gibt es keine wirkliche Anpassungs
    • UNION selbst ist (nicht UNION ALL) wird entfernen Sie doppelte Zeilen, auch wenn eine Eingabe keine Zeilen enthält

Beachten Sie, dass die UNION modifiziert werden könnte, um die Arbeit zu tun, obwohl dies nicht ideal ist:

SELECT nombre 
FROM (
    SELECT nombre 
    FROM dbo.internados 
    WHERE nombre = ? 
    UNION ALL 
    SELECT nombre 
    FROM dbo.universidades 
    WHERE nombre = ? 
) N 
GROUP BY nombre 
HAVING Count(*) = 2 
; 

Auf diese Weise stellen wir sicher, gibt es zwei Werte. Beachten Sie, dass davon ausgegangen werden kann, dass nicht zwei Namen in jeder Tabelle vorhanden sein dürfen. Wenn das stimmt, wäre mehr Arbeit nötig, um die UNION Methode dazu zu bringen, den Job zu machen.

+3

Danke, das ist eine großartige Erklärung von JOIN und UNION. Ich denke, dass ich sie zuerst missverstanden habe und dass ich das neu strukturieren muss. –

+4

Ich habe etwas mehr Details über 'JOIN' und' UNION' hinzugefügt. – ErikE

+0

und soll ich +1 für die richtige Version der 'Union' hinzufügen, die 'group by' und' having' verwendet. So wurden uns Dinge in der Schule beigebracht (zusammen mit den Lehrern, die immer sagten: "Benutze keine Gewerkschaften oder Unterabfragen, tritt FTW bei!") – zmo

5

ein die meiste Zeit union können, indem Sie eine Verknüpfung erreicht werden:

SELECT nombre 
    FROM internados 
UNION 
SELECT nombre 
    FROM universidades 
WHERE nombre = ? 

wäre besser:

SELECT nombre 
    FROM internados i 
    JOIN universidades u 
    ON i.nombre = u.nombre 
    AND nombre = ? 

Das ist viel einfacher zu lesen. (Sie können auch die JOIN Syntax verwenden, aber ich bevorzuge einfache alte manuelle Joins).

Aber ob dies ein union oder ein join, immer daran denken, dass beide Tabellen im Ergebnis verschmolzen erhalten:

nombre | todo | becas | fotos | ... | contenido | becas | ... 

so grundsätzlich, wie Sie eine Bedingung auf nombre setzen, entweder Sie eine leere bekommen festgelegt oder der Name, den Sie der Abfrage gegeben haben. Aber so wie Sie Ihre Vereinigung geschrieben haben, wird nur der zweite Satz die where Bedingung angewendet, nicht die erste. Du sollst den Zustand sowohl der Abfragen der Union setzen:

SELECT nombre 
    FROM internados 
WHERE nombre = ? 
UNION 
SELECT nombre 
    FROM universidades 
WHERE nombre = ? 
+3

Nicht-ANSI-Joins im alten Stil? Im Jahr 2013!?!? Zu was kommt die Welt? Ich kann das nicht empfehlen. – ErikE

+3

ok, ok, das zu beheben, du hast Recht, es ist Zeit, ich bin in SQL XXI Jahrhundert ;-) – zmo

+3

Ich war histrionic, aber danke fürs Zuhören. :) – ErikE

Verwandte Themen