Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Người dùng hoạt động hàng tuần cho mỗi ngày từ nhật ký

Để có số lượng "Người dùng trung bình hàng tuần" (theo hiểu biết của tôi về đặc điểm kỹ thuật của bạn ... "cho mỗi ngày, số lượng user_id riêng biệt được nhìn thấy trong ngày đó và sáu ngày trước đó"), hãy truy vấn dọc theo các dòng bên dưới có thể được sử dụng. (Truy vấn cũng trả về số lượng "Người dùng trung bình hàng ngày".

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

(Tôi chưa chạy thử nghiệm điều này; nhưng tôi sẽ kiểm tra sau và tôi sẽ cập nhật tuyên bố này nếu cần chỉnh sửa.)

Truy vấn này đang tham gia danh sách người dùng trong một ngày nhất định (từ u nguồn hàng), đến một tập hợp ngày từ bảng nhật ký (d Nguồn dữ liệu). Lưu ý chữ "7" xuất hiện trong vị từ tham gia (mệnh đề BẬT), đó là điều khiến danh sách người dùng "khớp" với 6 ngày trước.

Lưu ý rằng điều này cũng có thể được mở rộng để có được số lượng người dùng riêng biệt trong 3 ngày qua, chẳng hạn như bằng cách thêm một biểu thức khác trong danh sách CHỌN.

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

Chữ "7" theo nghĩa đen đó có thể được tăng lên để có phạm vi lớn hơn. Và chữ 3 trong biểu thức ở trên có thể được thay đổi để có bất kỳ số ngày nào ... chúng ta chỉ cần đảm bảo rằng chúng ta đã có đủ các hàng của ngày hôm trước (từ d ) được nối với mỗi hàng từ u .

LƯU Ý HIỆU SUẤT:Do các chế độ xem nội tuyến (hoặc các bảng dẫn xuất, như MySQL gọi chúng), truy vấn này có thể không nhanh lắm, vì các tập kết quả cho các chế độ xem nội tuyến đó phải được cụ thể hóa thành các bảng MyISAM trung gian.

Chế độ xem nội tuyến có bí danh là u có thể không tối ưu; tham gia trực tiếp vào bảng nhật ký có thể nhanh hơn. Tôi đã suy nghĩ về việc có được một danh sách người dùng duy nhất cho một ngày nhất định, đó là điều mà truy vấn trong chế độ xem nội tuyến đã giúp tôi. Nó chỉ dễ dàng hơn cho tôi để hình dung những gì đang diễn ra. Và tôi đã nghĩ rằng nếu bạn có hàng trăm người dùng giống nhau được nhập trong ngày, thì chế độ xem nội tuyến sẽ loại bỏ toàn bộ các bản sao, trước khi chúng tôi thực hiện tham gia vào những ngày khác. Điều khoản WHERE để giới hạn số ngày chúng tôi đang trở lại tốt nhất sẽ được thêm vào bên trong ud các chế độ xem nội tuyến. (d chế độ xem nội tuyến sẽ cần bao gồm thêm 6 ngày trước đó.)

Một lưu ý khác, nếu cột ts là kiểu dữ liệu TIMESTAMP, tôi sẽ có xu hướng sử dụng DATE(ts) biểu thức để trích xuất phần ngày tháng. Nhưng điều đó sẽ trả về kiểu dữ liệu DATE trong tập kết quả, thay vì một số nguyên, sẽ khác với tập kết quả bạn đã chỉ định.)

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ngoại lệ truy cập trình xử lý ngoại lệ MySQL đang được xử lý

  2. Biến mảng trong mysql

  3. mysqli_connect tới máy chủ từ xa

  4. Làm thế nào để viết truy vấn phức tạp này trong codeigniter?

  5. MySQL chọn một trường từ bảng điều kiện WHERE nằm trong nhiều hàng