2016-07-01 8 views
1

Ich entwickle gerade ein System zur Verwaltung von Mietprozessen und frage mich, wie man alle mietbaren Objekte effizient mit dem Personennamen abfragen kann, der sie gerade vermietet wenn das Objekt im Moment vermietet ist. Andernfalls sollte in dieser Spalte NULL sein.Richtig verbinden 1: n: 1: 1 Beziehung in Mysql Datenbank

Meine Tabellen wie folgt aussehen:

Objekt

| object_id | object_name | 
--------------------------- 
| 1   | Object A | 
| 2   | Object B | 
| 3   | Object C | 
| 4   | Object D | 
| 5   | Object E | 
--------------------------- 

Person

| person_id | person_name | 
--------------------------- 
| 1   | John Doe | 
| 2   | Jane Doe | 
| 3   | Max Muster | 
| 4   | Foobar  | 
--------------------------- 

Vermietung

| rental_id | rental_state| person_person_id | 
---------------------------------------------- 
| 1   | open  | 1    | 
| 2   | returned | 1    | 
| 3   | returned | 2    | 
| 4   | open  | 3    | 
| 5   | returned | 4    | 
---------------------------------------------- 

rental2object

| rental_rental_id | object_object_id | 
--------------------------------------- 
| 1    | 1    | 
| 2    | 2    | 
| 2    | 3    | 
| 3    | 3    | 
| 4    | 2    | 
| 4    | 5    | 
| 5    | 2    | 
--------------------------------------- 

Das Ergebnis, das ich sollte wie folgt aussehen wollen:

| object_id | object_name | rented_to  | 
------------------------------------------- 
| 1   | Object A | John Doe  | 
| 2   | Object B | Max Muster | 
| 3   | Object C | NULL   | 
| 4   | Object D | NULL   | 
| 5   | Object E | Max Muster | 
------------------------------------------- 

Was ich bisher ist bekam:

SELECT `object_id`, `object_name`, `person_name` FROM `object` 
LEFT JOIN `rental2object` ON `object_id` = `object_object_id` 
LEFT JOIN `rental` ON `rental_id` = `rental_rental_id` AND `rental_state` = 'open' 
LEFT JOIN `person` ON `person_id` = `person_person_id` 
GROUP BY `object_id` 

Das offensichtliche Problem ist dass ich nicht weiß, wie man beim Gruppieren richtig aggregiert.

Was wäre der effizienteste Weg, um mein Ziel zu erreichen? Schätze deine Hilfe.

EDIT

das erwartete Ergebnis wird korrigiert, so dass das Objekt B auch Max Muster vermietet.

+0

Es sind Spalten in Ihrer 'SELECT'-Anweisung, die nicht in' GROUP BY' existiert. – ydoow

+1

Objekte # 2 und # 5 sind beide in Vermietung # 4. Aber Sie gehen mit beiden auf unterschiedliche Weise auf Ihre erwarteten Ergebnisse ein. Objekt E und Objekt B sollten beide dasselbe Verhalten haben, beide mit Max Muster verwandt, ist es nicht? Warum Objekt B hat eine Null related_to Person? – danihp

+0

Ok, ich sehe deine Bearbeitung, dann überprüfe meine Antwort, wird von einigen Muggeln abgelehnt, ich weiß nicht warum. – danihp

Antwort

1

über Ihre Frage

Objekte # 2 und # 5 sind beide in Miete # 4. Aber bei Ihren erwarteten Ergebnissen behandeln Sie beide auf unterschiedliche Weise. Objekt E und Objekt B sollten beide dasselbe Verhalten haben, da sie sich in derselben Vermietung befinden. Wenn nicht, sollten Sie erklären, was die Kriterien sind, um zu wissen, ob ein Produkt eine verwandte Person hat oder nicht.

Gruppe von

Um SQL92 kompatibel sind Sie in select-Klausel alle nicht aggregierten Spalten enthalten sollen:

SELECT `object_id`, `object_name`, `person_name` as rented_to 
FROM `object` 
... 
GROUP BY `object_id`, `object_name`, `person_name` 

SQL99 kompatibel sein sollten Sie in select-Klausel alle nicht aggregierten Spalten enthalten nicht funktionell abhängig, in Ihrem Fall sind sie abhängig zwischen object_id und object_name: object_id -> object_name (das Feld rental_state bricht abhängige Funktionalität

SELECT `object_id`, `object_name`, `person_name` as rented_to 
FROM `object` 
... 
GROUP BY `object_id`, `person_name` 

5,7 MySQL: zu Person), dann können Sie einfach zu schreiben.5 und höher implementiert die Erkennung der funktionalen Abhängigkeit, dann ist diese letzte Auswahl gültig, aber ich schlage vor, dass Sie zur besseren Lesbarkeit die erste verwenden.

Lesen Sie MySQL Handling of GROUP BY für weitere Informationen und ONLY_FULL_GROUP_BY Parameterdetails.

Leistung

Seien Sie sicher, dass Sie Indizes für:

  • Objekt: Object_id (Primärschlüssel ist, dann ist Index implizit)
  • rental2object: object_object_id (kann ein Verbund sein Index mit dem anderen Feld, aber sicher sein object_object_id ist das erste Feld auf Index)
  • renta l: rental_id & rental_state (a Composite Index mit beiden Feldern)
  • Person: person_id (wird Primärschlüssel, dann Index ist implizit)
+0

Suche erneut Abfrage entspricht nicht gewünschte Ausgabe –

+0

Ich denke, basierend auf dem erwarteten Ergebnis, dass der letzte Status für Objekt b zurückgegeben wird, aber OPs Lösung denkt, dass dies offen und an Max Muster vermietet ist. Die Abfrage benötigt wahrscheinlich einen where-in-max-Test, um den letzten Status für das Objekt zu finden, und sollte nicht nach der open-in-Klausel testen. –

+0

Nein, habe ich nicht .... –

-1

starten

SELECT 
    o.object_id, 
    o.object_name, 
    p.person_name AS rent_to 
FROM 
    rental2object ro 
RIGHT JOIN object o ON ro.object_object_id = o.object_id 
LEFT JOIN rental r ON ro.rental_rental_id = r.rental_id AND r.rental_status = 'open' 
JOIN person p ON r.person_person_id = p.person_id 
+0

ist nicht richtig, Join zu Objekt sollte ein 'rechts äußerer Join' sein, um alle Objekte auszuwählen. – danihp

+0

@danihp das ist richtig. – ydoow

+0

Ich habe abgelehnt, weil das Problem nicht auf "aus Klausel" steht, auch Ihre Vorgehensweise war falsch. Ich entferne die Abstimmung, denke aber darüber nach. – danihp

-1
SELECT  `object_id`, `object_name`, 
       case 
        when rental_state = 'Open' then `person_name` 
        when r1.rental_rental_id is null then null 
       else `rental_state` 
       end as RentedTo 
FROM   `object` 
LEFT JOIN `rental2object` r1 ON `object_id` = r1.`object_object_id` 
LEFT JOIN `rental`     ON `rental_id` = r1.`rental_rental_id` 
LEFT JOIN `person`     ON `person_id` = `person_person_id` 
where   r1.rental_rental_id = 
       (select max(r2.`rental_rental_id`) 
        from `rental2object` r2 
        where r2.`object_object_id` = r1.`object_object_id` 
        group by r2.`object_object_id`) 
       or r1.rental_rental_id is null 
GROUP BY `object_id`;