2017-02-01 11 views
0

Ich versuche, eine Abfrage für die folgende Situation zu erstellen, aber ich kann es einfach nicht vom konzeptionellen zum tatsächlichen zu bekommen.SQL-Unterabfragen für Teilnahme Dieser Monat und letzter Monat

Ich habe drei Tabellen:

  • Profil (ID, First_Name, Last_Name)
  • Ereignis (ID, Datum)
  • Anwesenheit (Profile_ID, Event_ID)

Ich bin Ich versuche, eine Liste der Profile zu erhalten, die diesen Monat und letzten Monat besucht haben.

Bislang habe ich daran gedacht, beide Monate zu zählen und sie nur auszuwählen, wenn sie größer als 1 sind, aber ich habe es noch nicht ganz zum Laufen gebracht.

Etwas wie:

SELECT * FROM Profile 
LEFT OUTER JOIN Attendance ON Profile.ID = Attendance.Profile_ID 
LEFT OUTER JOIN Event ON Attendance.Event_ID = Event.ID 
WHERE [subquery to confirm attendance of this Profile_ID in this month/year > 1] 
AND [subquery to confirm attendance of this Profile_ID in last month/year > 1] 

So ist die erste Frage, ob ich über das Problem richtig denke und in einer guten Richtung bewege. Die zweite Frage ist, wie man diese Unterabfragen richtig macht - ich kann leicht etwas wie SELECT * FROM Attendance WHERE MONTH(Date) = 12 AND YEAR(Date) = 2016 machen, aber das würde eine Liste aller Besucherzahlen zurückgeben. Was ich wirklich will, ist eine Liste nur der Anwesenheit für jede ID einzeln - also wenn ich auf ID 4 schaue, möchte ich überprüfen, ob diese bestimmte ID eine Anwesenheit in diesem Monat und letzten Monat hat, aber ich bin nicht Sicher, wie man das zur WHERE-Klausel hinzufügt.

+0

1) haben - das ist eine Methode. Ein anderer besteht darin, verschiedene Monate zu zählen, deren Gesamtzahl der Anzahl der Argumente entspricht. Für 2) siehe http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-very-simple -sql-query – Strawberry

Antwort

1

ALLE AVOID FIRST STICHWÖRTER IN DEM Namen, wie Sie mit Datum taten Event(ID,Date) Um Ihre erste Frage zu beantworten: es ist logisch, so zu denken und es ist möglich, es zu bekommen. Über die Richtung denke ich, dass der linke Join-Ansatz in Ordnung ist, so dass das Hauptproblem auf dem Filter liegt. Da nun die 2. Teilnahme im Monat keine Rolle spielt, extrahieren wir nur den Monat vom Ereignisdatum, damit wir einen solchen Datensatz als Duplikat erhalten EXTRACT(MONTH FROM Events.event_date. Jetzt wäre die DATEDIFF() nicht geeignet, also verwenden wir die MONTH(), um die aktuellen und letzten Monatsereignisse zu erhalten. wenn die aktuelle Monat ist Januar (dh 1-12 = -11)

MONTH(CURRENT_DATE) - MONTH(Events.event_date) = 0 Ereignis im laufenden Monat MONTH(CURRENT_DATE) - MONTH(Events.event_date) = 1 gibt Veranstaltung im letzten Monat MONTH(CURRENT_DATE) - MONTH(Events.event_date) = -11 gibt Veranstaltung im Dezember gibt eine Liste der Profile für diejenigen Dies gibt die besucht in deutliche Monate. Als nächstes wählen Sie aus diesem Set nur diejenigen, die zweimal erscheinen. Tun Sie es mit dem GROUP BY x.id HAVING COUNT(x.id) = 2

so sollten Sie ja

SELECT x.id,x.first_name,x.last_name FROM (
    SELECT DISTINCT Profile.ID,Profile.first_name,Profile.last_name,Attendance.Profile_ID, EXTRACT(MONTH FROM Events.event_date) AS event_date FROM 
Profiles 
    LEFT OUTER JOIN Attendance ON Profile.ID = Attendance.Profile_ID 
    LEFT OUTER JOIN Events ON Attendance.Event_ID = Events.ID 
    WHERE (

      (MONTH(CURRENT_DATE) - MONTH(Events.event_date)) = 0 
      OR 
      (MONTH(CURRENT_DATE) - MONTH(Events.event_date)) = 1 
      OR 
      (MONTH(CURRENT_DATE) - MONTH(Events.event_date)) = -11 

     ) 
) AS x GROUP BY x.id HAVING COUNT(x.id) = 2 
+0

In Bezug auf die Verwendung des Keywords haben Sie Recht - ich habe es tatsächlich zu "Date" als eine Form der Anonymisierung geändert, der eigentliche Name ist etwas wie dateOfClass oder so ähnlich. In Bezug auf die Frage, würde das nicht Personen einschließen, die zweimal diesen Monat kamen, aber null Mal im Vormonat? Sie können das in Ihrem letzten Satz abdecken, aber ich bin nicht klar darüber – Jake

+0

Nur sah die Bearbeitung - vielen Dank! – Jake