2016-04-12 9 views
1

Ich habe Mühe, in einer Suchanfrage zu artikulieren, was ich versuche zu tun. Es tut mir leid, wenn das vorher beantwortet wurde. Ich hoffe, dass jemand mit einem vollständigen Beispiel mich in die richtige Richtung weisen kann. Ich möchte entweder eine MySQL-Abfrage herausfinden oder eine bessere Möglichkeit zur Strukturierung meiner Datenbank kennenlernen, um Folgendes zu ermöglichen.Eine Tabelle durch andere Tabellen mit einer anderen verbinden

Wenn ich 4 Tabellen habe, was ist der beste Weg, um durch eine Tabelle zu einer anderen zu verknüpfen. Unten habe ich eine site_table, die eine ID für einen Manager (General Manager der Site), eine Region und ein Land hat. Die region_table und country_table zeigen auch auf die manager_table. Die manager_id auf der site_table zeigt auch auf die manager_table. Hier sind, was die Tabellen aussehen kann:

site_table 
+------------+------------+-----------+------------+ 
| name | manager_id | region_id | country_id | 
+------------+------------+-----------+------------+ 
| Manchester |   1 |   1 |   1 | 
| Essex  |   2 |   2 |   1 | 
| Perth  |   3 |   3 |   2 | 
| Birmingham |   4 |   1 |   1 | 
+------------+------------+-----------+------------+ 

region_table 
+-----------+---------+------------+ 
| region_id | name | manager_id | 
+-----------+---------+------------+ 
|   1 | Central |   5 | 
|   2 | South |   6 | 
|   3 | North |   7 | 
+-----------+---------+------------+ 

country_table 
+------------+----------+------------+ 
| country_id | name | manager_id | 
+------------+----------+------------+ 
|   1 | England |   9 | 
|   2 | Scotland |   8 | 
+------------+----------+------------+ 

manager_table 
+------------+-----------------+ 
| manager_id |  name  | 
+------------+-----------------+ 
|   1 | Joe Bloggs  | 
|   2 | Graham Smith | 
|   3 | Pat Sharp  | 
|   4 | Sally May  | 
|   5 | Peter Barratt | 
|   6 | Jimmy Stone  | 
|   7 | Kim Keller  | 
|   8 | Peter Sheet  | 
|   9 | Matthew Lampart | 
+------------+-----------------+ 

Ich möchte die Datenbank abzufragen, um die Site-Namen zurück, General Manager (GM) Name, Regional Manager (RM) Name und Country Manager der (CM) Namen wie so:

+------------+--------------+---------------+-----------------+ 
| site_name | GM_name | RM_name |  CM_name  | 
+------------+--------------+---------------+-----------------+ 
| Manchester | Joe Bloggs | Peter Barratt | Matthew Lampart | 
| Essex  | Graham Smith | Jimmy Stone | Matthew Lampart | 
| Perth  | Pat Sharp | Kim Keller | Peter Sheet  | 
| Birmingham | Sally May | Peter Barratt | Matthew Lampart | 
+------------+--------------+---------------+-----------------+ 

ich mag das Gefühl, dies zu tun, würde ich die site_table zum region_table und country_table zu verbinden habe, und verknüpfen Sie dann die manager_table zum site_table, region_table und country_table aber ich binde mich in Knoten nach oben versuchen es zu tun. Ich sehe die Links wie folgt aussehen:

site_table---+-----------------------+ 
      |      | 
      +-----region_table----manager_table 
      |      | 
      +----country_table------+ 

Wenn jemand irgendwelche Ratschläge über die beste Art und Weise geben können diese Abfrage zu schreiben, oder einen besseren Weg, um die Datenbank zu strukturieren, die wirklich hilfreich wäre.

+0

Dies sieht wie ein vernünftiges Schemadesign aus, * es sei denn * die einzige Information, die für einen Manager gespeichert wird, ist ihr Name (was unwahrscheinlich erscheint). –

+0

Dank @MarkBannister, Sie haben Recht, es gibt mehr Informationen in der Manager-Tabelle – SBmore

Antwort

2

Versuchen Sie die bedingte Aggregation mit CASE EXPRESSION. Ihre Idee ist richtig, Sie müssen zuerst alle drei Tabellen verbinden, und dann, wie Sie sehen können, trat ich mit Manager-Tabellen auf m.manager_id IN(s.manager_id,r.manager_id,c.manager_id). Die Aggregation nach ist die Ausgabe zu pivotieren, da es für jeden Namen 3 Datensätze gibt, die manager_name für jede der Tabellen enthält.

SELECT s.name, 
     MAX(CASE WHEN s.manager_id = m.manager_id THEN m.name END) as GM_NAME, 
     MAX(CASE WHEN r.manager_id= m.manager_id THEN m.name END) as RM_NAME, 
     MAX(CASE WHEN c.manager_id = m.manager_id THEN m.name END) as CM_NAME 
FROM site_table s 
INNER JOIN region_table r ON(s.region_id = r.region_id) 
INNER JOIN country_table c ON(s.country_id = c.country_id) 
INNER JOIN manager_table m ON(m.manager_id IN(s.manager_id,r.manager_id,c.manager_id)) 
GROUP BY s.name 

Wenn Sie fehlende Daten haben kann - nulls auf einem der site_table id Spalten, die nicht sehr vernünftig klingt durch die Daten, die Sie zur Verfügung gestellt und auch von der Idee dieser Struktur, dann links verwenden

SELECT s.name, 
     MAX(CASE WHEN s.manager_id = m.manager_id THEN m.name END) as GM_NAME, 
     MAX(CASE WHEN r.manager_id= m.manager_id THEN m.name END) as RM_NAME, 
     MAX(CASE WHEN c.manager_id = m.manager_id THEN m.name END) as CM_NAME 
FROM site_table s 
LEFT JOIN region_table r ON(s.region_id = r.region_id) 
LEFT JOIN country_table c ON(s.country_id = c.country_id) 
LEFT JOIN manager_table m ON(m.manager_id IN(s.manager_id,r.manager_id,c.manager_id)) 
GROUP BY s.name 
+0

interessant ... noch nie zuvor gesehen – dotjoe

+0

Vielen Dank @sagi für Ihre Lösung, es hat perfekt funktioniert. Ich interessiere mich für den Teil MAX (CASE WHEN ... THEN ... END), ich werde auf jeden Fall mehr darüber lesen, wie das funktioniert. Danke noch einmal. – SBmore

+0

@SBmore, dass 'MAX (CASE..' wird verwendet, um alle Datensätze zu einem einzigen zu vereinigen, die Gruppe von ist nicht genug. Denken Sie darüber nach, wenn ich nach gruppieren und ein normales max (m.Name), es gibt derzeit 3 ​​Manager Namen für jeden Namen, so wird der Fall verwendet, um für jede Spalte zu bestimmen, welche verwendet werden soll, und die max ist, weil, wenn die Bedingung in der 'CASE ..' nicht Fleisch Es wird Nullwert und Max wird den Namen annehmen. Hoffe, ich habe es klarer gemacht – sagi

3

verbinden So ist die einfache Antwort ist:

select 
    s.name site_name, 
    gm.name GM_name, 
    rm.name RM_name, 
    cm.name CM_name 
from 
    site_table s 
    inner join manager_table gm on gm.manager_id = s.manager_id 
    inner join region_table r on r.region_id = s.region_id 
    inner join manager_table rm on rm.manager_id = r.manager_id 
    inner join country_table c on c.country_id = s.country_id 
    inner join manager_table cm on cm.manager_id = c.manager_id; 

Aber das wirklich funktioniert nur, wenn es eine immer mindestens eine Region d Manager für jeden GM, RM und CM. Etwas ein wenig flexibler sein könnte:

select 
    s.name site_name, 
    gm.name GM_name, 
    rm.name RM_name, 
    cm.name CM_name 
from 
    site_table s 
    left outer join manager_table gm on gm.manager_id = s.manager_id 
    left outer join region_table r on r.region_id = s.region_id 
    left outer join manager_table rm on rm.manager_id = r.manager_id 
    left outer join country_table c on c.country_id = s.country_id 
    left outer join manager_table cm on cm.manager_id = c.manager_id; 

Welche Situationen handhaben, wo Sie Manager oder Regionen fehlen, aber ist etwas weniger effizient.

Hoffe diese Hilfe!

+0

6 Joins ist 2 unnötige Joins! – sagi

+0

Danke für Ihre Hilfe @CaffeineFueled. Ich habe Sagis Lösung benutzt, um die Menge der Joins zu reduzieren. Danke nochmal für die Antwort – SBmore

Verwandte Themen