Viết Query ORM cho trường hơp này!
Mình có code như hình bên dưới.
Vì trong khi lấy dữ liệu có vòng lặp foreach nên "Sếp" bảo chưa ok. Mình tìm mãi mà chưa ra cách nào viết query thay được vòng lặp for.( sếp đang bận, nên không hỏi được nha các bác.)
Mô tả: Em lấy 1 mảng chứa các User -> từ user_id lấy thêm các trường giá trị để tạo bảng lương. Hi vọng cao nhân nào đi qua chỉ em phát!
2 CÂU TRẢ LỜI
lấy ví dụ như sale_direct, thay vì query theo 1 $user->id, thì where in array $user->id, lưu vào mảng tên là $arraySaleDirect. sau đó trong vòng foreach thì đọc data từ $arraySaleDirect ra. mấy cái khác xử lí tương tự.
Cảm ơn bác nhé! nhưng vấn đề mình đang gặp phải lại là hàm tính SaleDirect lại là một hàm sum.
M thay hàm where = whereIn mà chưa nghĩ ra!
group theo user->id là xong rồi
@kietcuabe "where in array $user->id" lúc mình làm theo idea này loay hoay mãi không được, rồi phải groupby xong check chuyển thành array, Hời lằng nhằng nhưng tốc đổ xử lý nhanh gấp đôi, query từ 144->14 ) Dù sao cũng cảm ơn b nhé!
@tab99 muốn optimize thì phải chấp nhận thôi bác :3 muốn nhanh thì lấy data đổ vào RAM rồi đọc từ RAM ra, khi nào devops báo server thường xuyên hết RAM thì chuyển qua where by $user->id chạy nhiều câu query. Cho nên code không chưa đủ, phải vận hành và monitor hệ thống mới thấy nhiều vấn đề.
Cái này sếp bạn bắt code lại là đúng rồi, mình đang thấy bạn gọi đến 6 câu query cho 1 user. Hãy tưởng tượng bạn có đến 10000 user thì tổng số lượng query nó lên đến 60000 cho đoạn đó. Theo mình có 2 cách để refactor:
- Sử dụng ít câu truy vấn hơn thông qua các mệnh đề có sẵn trong SQL (select, join, blabla...)
- Mình đang thấy đoạn trong vòng lặp là bạn đang muốn thống kê hiệu xuất bán hàng của user. Nếu dữ liệu nhiều mình nghĩ nên có 1 bảng thống kê riêng, bạn sẽ có 1 batch chạy ngầm để tổng hợp dữ liệu -> lưu vào bảng thống kê theo user_id. Như vậy chỉ cần join bảng users với bảng thống kê đó là xong.
BTW, nếu dữ liệu siêu siêu lớn bạn có thể tham khảo bài viết sau: https://viblo.asia/p/he-thong-analytic-suong-suong-tu-du-lieu-30-trieu-nguoi-dung-vyDZOwwRZwj
cảm ơn bác!
Chào bạn. Mình không rõ bạn đã giải quyết được vấn này hay chưa? Nhưng mình có 1 cách giải quyết gộp truy vấn của bạn lại và khuyên bạn không nên dùng đoạn for sẽ làm cấp số nhân số lần truy vấn vào database. Bạn tham khảo cách của mình nhé:
$this->userRepository->getModel()->with('terminateContract')
->addSelect(
DB::raw('SUM(CASE
WHEN terminateContract.status = 2
THEN terminateContract.amount
ELSE 0 END) AS sale_direct')
)
->addSelect(
DB::raw('SUM(CASE
WHEN terminateContract.status = 1
THEN terminateContract.amount
ELSE 0 END) AS sale_in_direct')
)
->where('terminateContract.startdate', $startDate)
->where('terminateContract.enddate', $endDate)
Phần ->with('terminateContract') bạn nhớ viết relationship trong model nhé. Trong ảnh mình thấy bạn có 3 hàm getAllRewardUserIdByMoth, getAllPunishdUserIdByMoth, getTotalCommission. Mình không rõ 3 hàm này dùng để xử lý logic hay là trỏ đến 1 model nào khác hay không nên không thể gộp vào truy vấn như bên trên cho bạn.