sql >> Databáze >  >> RDS >> Mysql

Týdenní aktivní uživatelé za každý den z protokolu

Chcete-li získat počet „týdenního průměrného uživatele“ (podle mého chápání vaší specifikace... „za každý den, počet odlišných user_id zaznamenaných během daného dne a předchozích šesti dnů“), použijte dotaz ve smyslu níže uvedeného mohl být použit. (Dotaz také vrátí počet „Denního průměrného uživatele“.

SELECT d.day
     , COUNT(DISTINCT u.user_id) AS wau
     , COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
  FROM ( SELECT FLOOR(k.ts/86400) AS `day`
           FROM `log` k
          GROUP BY `day`
       ) d
  JOIN ( SELECT FLOOR(l.ts/86400) AS `day`
              , l.user_id
           FROM `log` l
          GROUP BY `day`, l.user_id
       ) u
    ON u.day <= d.day
   AND u.day > d.day - 7
 GROUP BY d.day
 ORDER BY d.day

(Ještě jsem to neprovedl, ale udělám to později a toto prohlášení aktualizuji, pokud budou potřeba nějaké opravy.)

Tento dotaz se připojuje k seznamu uživatelů pro daný den (z u rowsource), na sadu dní z tabulky protokolu (d rowsource). Všimněte si doslovné „7“, která se objevuje v predikátu spojení (klauzule ON), to je to, co seznam uživatelů „přiřazuje“ k předchozím 6 dnům.

Všimněte si, že toto lze také rozšířit, abyste získali odlišný počet uživatelů za poslední 3 dny, například přidáním dalšího výrazu do seznamu SELECT.

     , COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day

Tato doslovná "7" by mohla být zvýšena, aby se získal větší rozsah. A ten doslovný 3 ve výše uvedeném výrazu lze změnit tak, aby získal libovolný počet dní... jen se musíme ujistit, že máme dostatek řádků předchozího dne (z d ) připojené ke každému řádku z u .

POZNÁMKA K VÝKONU:Vzhledem k inline pohledům (nebo odvozeným tabulkám, jak je nazývá MySQL), tento dotaz nemusí být příliš rychlý, protože sady výsledků pro tyto inline pohledy musí být materializovány do přechodných tabulek MyISAM.

Vložený pohled s aliasem u nemusí být optimální; může být rychlejší připojit se přímo k tabulce protokolů. Přemýšlel jsem o získání jedinečného seznamu uživatelů pro daný den, což je to, co mi tento dotaz v inline pohledu dostal. Bylo pro mě jednodušší představit si, co se děje. A myslel jsem si, že pokud zadáte stovky stejných uživatelů na den, inline zobrazení vyřadí spoustu duplikátů, než se připojíme k dalším dnům. Klauzule WHERE omezující počet dní vracející se by bylo nejlepší přidat do u a d vložené pohledy. (d vložené zobrazení by muselo obsahovat dalších 6 dní navíc.)

Další poznámka, pokud je sloupec ts datovým typem TIMESTAMP, byl bych více nakloněn použití DATE(ts) výraz pro extrakci části data. Ale to by vrátilo datový typ DATE v sadě výsledků, nikoli celé číslo, které by se lišilo od vámi zadané sady výsledků.)

SELECT d.day
     , COUNT(DISTINCT u.user_id) AS wau
     , COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
  FROM ( SELECT DATE(k.ts) AS `day`
           FROM `log` k
          GROUP BY `day`
       ) d
  JOIN ( SELECT DATE(l.ts) AS `day`
              , l.user_id
           FROM `log` l
          GROUP BY `day`, l.user_id
       ) u
    ON u.day <= d.day
   AND u.day > DATE_ADD(d.day, INTERVAL -7 DAY)
 GROUP BY d.day
 ORDER BY d.day


  1. MySQL:Omezte dva sloupce tak, aby jeden z nich byl vždy NULL

  2. Vytvoření systému slevových kódů (MySQL/php)

  3. Jak přesně fungují transakce s PHP PDO se souběžností?

  4. Jak opravím poškození InnoDB zamykání názvu tabulky od vytvoření (errno:-1) na AWS RDS?