2010-12-08 2 views
2

Angenommen, Sie haben eine Tabelle wie:Wie kann ich anhand eines Datumsbereichs feststellen, wie viele Benutzer 3-5 Tage pro Woche aktiv waren?

CREATE TABLE `checkins` (
    `id` bigint(20) NOT NULL default '0', 
    `userid` bigint(20) default NULL, 
    `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `ind_userid` (`userid`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

auf einem Datumsbereich Basierend, wie kann ich, wie viele Nutzer sagen aktiv waren 3-5 Tage pro Woche.

So etwas wie

input - two months date range 
output - 310 users were active 3-5 days a week 
+0

Tragen Sie jeden Tag in diese Tabelle für jeden Benutzer ein? –

+0

Es können mehrere Einträge desselben Benutzers für einen Tag sein. – Pentium10

Antwort

1

Wenn Sie einen Kalender Tabelle mit einer Zeile für jede Woche erstellt haben, sollten Sie in der Lage sein, Ihr Problem wie dieses mit einer Abfrage zu lösen:

SELECT userid 
FROM (SELECT userid, 
       YEARWEEK(TIMESTAMP)     AS year_week, 
       COUNT(DISTINCT DAYOFWEEK(TIMESTAMP)) AS check_in_days 
     FROM checkins 
     WHERE 1 = 1 -- This would be your date range filter 
     GROUP BY userid, 
        YEARWEEK(TIMESTAMP) 
     HAVING check_in_days BETWEEN 3 AND 5) AS user_weeks 
GROUP BY userid 
HAVING COUNT(year_week) = (SELECT COUNT(*) 
          FROM year_week 
          WHERE 1 = 1 -- This would be your date range filter 
         ); 

(Meine Woche Tabelle hat hier eine Zeile für jede Woche zwischen Jahre 2001 und 2020.)

Die innere Abfrage (user_weeks) gibt eine Zeile für jede {user_id, week} zurück, in der der Benutzer mindestens 3 Tage oder höchstens 5 Tage in dieser bestimmten Woche eingecheckt hat. (Nr Checkins pro Tag ist egal). Die äußere Abfrage gibt eine Zeile für jede {user_id} zurück, zusammen mit der Anzahl der Wochen, die die eingecheckte Anforderung von 3-5 Tagen erfüllt haben. Die having-Klausel im äußeren Auswahlfilter bewirkt, dass das Ergebnis nur Nutzer enthält, die so oft (Wochen) eingecheckt haben, wie die Anzahl der tatsächlichen Wochen in Ihrem Datumsbereich. Dies sollte die Anforderung "aufeinanderfolgender Wochen" erfüllen.

Lassen Sie mich wissen, ob dies Ihnen hilft.

Bearbeiten Geändert von Funktionswoche() zu Yearweek().

+0

Das gleiche Problem wie andere haben. Es zählt auch Wochen aus früheren Jahren. – Pentium10

+0

Bearbeitet, um stattdessen yearweek() zu verwenden. Jetzt wird Woche 2 in 2009 als eine andere Woche als Woche 2 in 2010 angesehen. Funktioniert es jetzt? Die Tabelle year_week sollte Einträge im Format YYYYWW haben, d. H. 200902, 200903, 201002 usw. – Ronnis

0

Dies ist in Orakel aber ich denke, kann es leicht in mysql zu

SELECT year_week AS year_week, 
     COUNT (year_week) AS days 
FROM ( SELECT TO_CHAR (timestamp, 'D') AS day_of_week, 
         TO_CHAR (timestamp, 'YYYY') 
        || '-' 
        || TO_CHAR (timestamp, 'WW') 
         AS year_week 
      FROM checkins 
     GROUP BY  TO_CHAR (timestamp, 'YYYY') 
        || '-' 
        || TO_CHAR (timestamp, 'WW'), 
        TO_CHAR (timestamp, 'D') 
     ORDER BY year_week) 
GROUP BY year_week order by year_week;  

TO_CHAR(timestamp, 'WW') = WEEKOFYEAR

TO_CHAR(timestamp, 'D') = DAYOFWEEK

+0

Das weiß ich, aber wie sagt das mir, dass sie jede Woche mindestens 3 verschiedene Tage und die meisten 5 verschiedenen Tage besucht haben. Die Frage ist nicht, welche Methoden zu verwenden sind. – Pentium10

+0

Können Sie sie nicht nach Wochentag und Wochentag gruppieren und dann auf die Zeilen zählen? –

+0

Das ist nicht so einfach, wie Sie anfangs dachten. Ich muss wissen, dass es alle Wochen in dem angegebenen Zeitraum passiert ist, kontinuierlich ohne Pause. Jede Woche. Eine einfache Zählung hilft nicht. – Pentium10

0

Er gilt als einer multi- erfolgen Abfrageproblem, wobei:

  • Ergebnis von der ersten Abfrage abgeleitet
  • secondResult von der zweiten Abfrage abgeleitet ist
  • minDate ist der minimale Zeitpunkt im Bereich, angegeben als äquivalent zu WEEKOFYEAR(minDate)
  • MaxDate ist das maximale Datum im Bereich, angegeben als äquivalent zu WEEKOFYEAR(maxDate)
  • Die Spaltennamen userid und Zeitstempel immer
  • erhalten

Eine Lösung würde wie folgt aussehen:

SELECT DISTINCT userid, timestamp from checkins WHERE WEEKOFYEAR(timestamp) >= minDate and WEEKOFYEAR(timestamp) <= maxDate GROUP BY userid,DAYOFWEEK(timestamp); 
SELECT userid, timestamp FROM result GROUP BY userid,WEEKOFYEAR(timestamp) HAVING COUNT(timestamp) >= 3 AND COUNT(timestamp) <= 5; 
SELECT COUNT(*) FROM secondResult GROUP BY userid HAVING COUNT(timestamp) = (WEEKOFYEAR(maxDate) - WEEKOFYEAR(minDate)); 

Offensichtlich stellen Sie sicher, 52 in Fällen hinzuzufügen, wo der Kalender um hüllt. Ich habe dieses Parsen verifiziert und bin einigermaßen zuversichtlich, dass daraus eine korrekte Lösung abgeleitet werden kann.

+0

Faire Warnung: unvollkommene Lösung. Ich habe versucht, alle Faktoren in meiner Antwort zu berücksichtigen, indem ich herausruft, wo Sie eine Unterabfrage oder eine temporäre Tabelle verwenden können, um den Abfragen beizutreten, und wo Sie den Kalenderumlauf berücksichtigen müssen. – MrGomez

+0

Group by WeekOfYear berücksichtigt nicht mehrere Jahre. Es fasst die ganze Woche von früheren Jahren zusammen. – Pentium10

Verwandte Themen