Truy vấn này được sửa đổi từ truy vấn tôi đã viết ở đây: Phân tích theo nhóm trong SQL
Đây là truy vấn cuối cùng:
SELECT
STR_TO_DATE(CONCAT(tb.cohort, ' Monday'), '%X-%V %W') as date,
size,
w1,
w2,
w3,
w4,
w5,
w6,
w7
FROM (
SELECT u.cohort,
IFNULL(SUM(s.Offset = 0), 0) w1,
IFNULL(SUM(s.Offset = 1), 0) w2,
IFNULL(SUM(s.Offset = 2), 0) w3,
IFNULL(SUM(s.Offset = 3), 0) w4,
IFNULL(SUM(s.Offset = 4), 0) w5,
IFNULL(SUM(s.Offset = 5), 0) w6,
IFNULL(SUM(s.Offset = 6), 0) w7
FROM (
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
) as u
LEFT JOIN (
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
) as s ON s.UserId = u.UserId
GROUP BY u.cohort
) as tb
LEFT JOIN (
SELECT DATE_FORMAT(AddedDate, "%Y-%u") dt, COUNT(*) size FROM users GROUP BY dt
) size ON tb.cohort = size.dt
Vì vậy, cốt lõi của việc này là chúng tôi lấy người dùng và ngày họ đăng ký và định dạng ngày theo số năm-tuần, vì chúng tôi đang thực hiện nhóm thuần tập hàng tuần.
SELECT
UserId,
DATE_FORMAT(AddedDate, "%Y-%u") AS cohort
FROM users
Vì chúng tôi muốn nhóm theo nhóm thuần tập, chúng tôi phải đặt điều này vào một truy vấn con trong phần FROM của truy vấn.
Sau đó, chúng tôi muốn tham gia thông tin thanh toán trên người dùng.
SELECT DISTINCT
payments.UserId,
FLOOR(DATEDIFF(payments.PaymentDate, users.AddedDate)/7) AS Offset
FROM payments
LEFT JOIN users ON (users.UserId = payments.UserId)
Điều này sẽ nhận được các sự kiện thanh toán hàng tuần duy nhất cho mỗi người dùng theo số tuần họ đã là người dùng. Chúng tôi sử dụng phân biệt vì nếu một người dùng thực hiện 2 lần mua hàng trong một tuần, chúng tôi không muốn tính rằng đó là hai người dùng.
Chúng tôi không chỉ sử dụng bảng thanh toán vì một số người dùng có thể đăng ký và không có thanh toán. Vì vậy, chúng tôi chọn từ bảng người dùng và tham gia vào bảng thanh toán.
Sau đó, bạn nhóm theo tuần - u.cohort. Sau đó, bạn tổng hợp các con số trong tuần để tìm xem có bao nhiêu người đã thực hiện thanh toán trong những tuần sau khi họ đăng ký.
Phiên bản mysql tôi đã sử dụng có sql_mode được đặt thành only_full_group_by. Vì vậy, để có được kích thước nhóm thuần tập, tôi đặt phần lớn truy vấn trong truy vấn con để tôi có thể kết hợp với những người dùng để có được kích thước của nhóm thuần tập.
Cân nhắc thêm:
Lọc theo tuần rất đơn giản. tb.cohort> ngày bắt đầu và tb.cohort
Bạn có thể muốn xem xét sử dụng bảng lịch để giải quyết các trường hợp không có người dùng đăng ký trong tuần.
Đây là một thử thách với mọi thứ hoạt động: http://sqlfiddle.com/#!9/172dbe/ 1