"주간 평균 사용자 수"(귀하의 사양을 이해할 때마다 ... "매일 해당 일과 이전 6 일 동안 본 고유 한 user_ids 수")를 얻으려면 해당 줄에 대한 쿼리 아래에있는 것 중 하나를 사용할 수 있습니다. (쿼리는 또한 "일 평균 사용자"수를 반환
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
는 (나는 아직이의 테스트를 실행하지 않은;..하지만 나중에 것이며, 어떤 수정이 필요한 경우, 나는이 문장을 업데이트합니다)
이 쿼리는 주어진 날 (u
rowsource에서)의 사용자 목록을 로그 테이블 (d
rowsource)의 일 집합에 합류합니다. 조인 조건 자에 나타나는 리터럴 "7" ON 절), 이는 이전 6 일간 사용자 목록을 "일치"시키는 것입니다.
예를 들어, SELECT 목록에 다른 표현식을 추가하여 지난 3 일 동안 별개의 사용자 수를 얻습니다.
, COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day
더 큰 범위를 얻으려면 리터럴 "7"을 증가시킬 수 있습니다. 위의 표현에서 문자 3은 임의의 일 수를 얻기 위해 변경 될 수 있습니다 ... 우리는 u
에서 각 행에 결합 된 전날 행 (d
)을 충분히 확보해야합니다.
성능 참고 : 인라인 뷰 (또는 파생 테이블, MySQL이 호출하기 때문에) 때문에 이러한 인라인 뷰에 대한 결과 집합은 중간 MyISAM 테이블로 구체화되어야하므로이 쿼리는 매우 빠르지 않을 수 있습니다.
u
으로 앨리어싱 된 인라인보기는 최적이 아닐 수 있습니다. 로그 테이블에 직접 결합하는 것이 더 빠를 수도 있습니다. 주어진 날에 대한 고유 한 사용자 목록을 얻는 관점에서 인라인보기의 해당 쿼리가 나에게 어떤 생각인지 생각하고있었습니다. 무슨 일이 일어나고 있는지 개념화하는 것이 더 쉬웠습니다. 그리고 나는 당신이 같은 날에 수백 명의 동일한 사용자를 입력했다면 인라인 뷰는 우리가 다른 날과 합류하기 전에 복제물 전체를 제거 할 것이라고 생각했습니다. 반환 할 일수를 제한하는 WHERE 절은 u
및 d
인라인보기 내에 가장 잘 추가됩니다.합니다 (d
인라인 뷰는 이전 추가 육일을 포함해야합니다.)
또 다른 메모에서, TS 열이 TIMESTAMP 데이터 타입의 경우, 내가 날짜 부분을 추출하는 DATE(ts)
표현을 사용하는 경향이있을 것이다. 그러나 사용자가 지정한 결과 집합에서 다른 것 정수가 아닌, 결과 집합에 날짜 데이터 유형을 반환합니다.)
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
다음
매우 완벽한 답변을 주셔서 감사합니다. ts는 bigint입니다. 첫 번째 쿼리는 효율성에 관계없이 완벽하게 작동합니다 (현재로서는 충분히 효율적입니다). – Protected