2017-09-27 4 views
0

Ich habe eine Anwendung, die Schulferien behandelt. Leider gibt es drei verschiedene Schulferien: landesweite, landesweite und stadtweite Ferien. Ich speichere alle Daten in einer Tabelle days, einem Tisch vacation_periods und eine Verbindungstabelle slots:LEFT JOIN gehören Daten

days { 
    id:integer 
    date_value:date 
} 
slots { 
    id:integer 
    day_id:integer 
    vacation_period_id:integer 
} 
vacation_periods { 
    id:integer 
    starts_on:date 
    ends_on:date 
    name:string 
    country_id:integer 
    federal_state_id:integer 
    city_id:integer 
} 

ich alle days innerhalb eines bestimmten Zeitrahmens auswählen möchten. Nehmen wir an, 1. Januar 2017 bis 31. Januar 2017. ich diese days mit bekommen:

SELECT * FROM days WHERE date_value >= '2017-01-01' AND 
         date_value <= '2017-01-31'; 

Aber für meinen Urlaub Kalender brauche ich nicht nur die days sondern auch die Informationen, die vacation_periods innerhalb sind. Unter der Annahme, ich für alle vacation_periods suchen, die in diesem Zeitrahmen sind und die

country_id == 1 or federal_state_id == 5 or city_id == 30 

ich gelesen habe über JOINS und LEFT beitritt, das scheint die Lösung für das Problem zu sein. Aber ich kann nicht alles zusammen bekommen.

Ist es möglich, eine SQL-Anfrage zu senden, die all days innerhalb des gewünschten Zeitrahmen gibt und die zusätzliche Informationen, wenn ein vacation_period, die die country_id == 1 or federal_state_id == 5 or city_id == 30 Regel paßt über slots zu jedem day verbunden. Einschließlich der Name dieser vacation_period?

Wenn eine Anfrage nicht möglich ist: Welcher ist der schnellste Weg, dies in der Datenbank zu lösen? Wie viele Anfragen? Welche Art von Anfragen?

Wenn möglich, möchte ich ein Ergebnis in einer Art dieser Form zu erhalten:

- date_value: "2017-01-01" 
- date_value: "2017-01-02" 
- date_value: "2017-01-03" 
    * vacation_period.id: 15 
    * vacation_period.name: "foobar" 
- date_value: "2017-01-04" 
    * vacation_period.id: 15 
    * vacation_period.name: "foobar" 
- date_value: "2017-01-05" 
    * vacation_period.id: 15 
    * vacation_period.name: "foobar" 
- date_value: "2017-01-06" 
- date_value: "2017-01-07" 
... 
+1

Bitte geben Sie ein Beispiel für die Ausgabe, die Sie suchen. – dhiman

+0

Was ist der Zweck von "Slots"? –

+0

@AndrewLazarus Kein Zweck. Ich dachte, es ist die beste Lösung. Ich bin offen für andere Ideen. – wintermeyer

Antwort

1

Die folgende Abfrage könnte Ihnen die Antwort, die Sie suchen:

SELECT * FROM days WHERE date_value >= '2017-01-01' AND date_value <='2017-01-31' 

INNER JOIN slots ON days.id = slots.day_id 

INNER JOIN vacation_periods ON vacation_periods.id = slots.vacation_period_id 
+0

Sie können den ersten [INNER JOIN] für einen [LEFT OUTER JOIN] ersetzen, wenn alle Tage angezeigt werden sollen.Behalten Sie den Rest der Abfrage so, wie sie ist. –

+0

Kann ich dies verwenden, um nur die Urlaubstermine mit country_id == 1 oder federal_state_id == 5 oder city_id == 30 zu verbinden? Wie? – wintermeyer

+0

Versuchen Sie die folgende Abfrage dann. Es verwendet Unterabfragen, um die Tabelle zu filtern. Es wird ein bisschen komplex und ich kann es nicht ausprobieren, also funktioniert es nicht garantiert. SELECT FROM Tage * WHERE date_value> = '2017.01.01' AND date_value <= '2017.01.31' LEFT OUTER JOIN-Steckplätze auf days.id = slots.day_id INNER JOIN (select * from vacation_periods where country_id = 1 ODER föderaler_status_id = 5 ODER city_id = 30) wie filtered_vacation_periods ON filtered_vacation_periods.id = slots.vacation_period_id –

0

Ich denke, Sie können eine unformatierte Version von dem erhalten, was Sie wollen (das in eine hierarchische Ausgabe verarbeitet werden könnte) mit

ändern, um vacation_period haben nur eine ID, und ein neues Feld authority des Typs vacation_authority. Sie können nun einen Primärschlüssel entweder aus dem ID-Feld oder (ID, Berechtigung) erstellen, je nachdem, wie die Urlaubsdaten in das System gelangen.

Wenn es jetzt mehrere Feiertage gibt, die sich über ein bestimmtes Datum erstrecken, handelt es sich um mehrere Datensätze in der Ausgabe. Es ist nicht klar, was Sie in diesem Fall wollen.

0

Keine der anderen Antworten konnte mein Problem lösen, aber sie ließen mich zu der Lösung, also bin ich dankbar für sie. Hier ist die Lösung:

SELECT days.date_value, slots.period_id, vacation_periods.name FROM days 
LEFT OUTER JOIN slots ON (days.id = slots.day_id) 
LEFT OUTER JOIN vacation_periods ON (slots.period_id = vacation_periods.id) 
WHERE days.date_value >= '2017-01-05' 
AND days.date_value <='2017-01-15' 
AND (vacation_periods.id IS NULL 
OR vacation_periods.country_id = 1 
OR vacation_periods.federal_state_id = 5) 
ORDER BY days.date_value; 

Screenshot of the SQL Query output.