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

Cách trả về các hàng bị thiếu trong bảng - Báo cáo Vắng mặt của Nhân viên

Nếu "vắng mặt" được xác định là sự không xuất hiện của một hàng trong emp_tx bảng cho một empcode cụ thể cho một ngày cụ thể (date =nửa đêm đến nửa đêm trong khoảng thời gian 24 giờ) và ...

Nếu có thể chấp nhận được nếu không hiển thị "vắng mặt" cho một ngày KHÔNG có giao dịch nào trong emp_tx bảng cho ngày đó (tức là loại trừ một ngày mà TẤT CẢ các mã trống vào ngày đó), sau đó ...

Bạn có thể lấy bốn cột đầu tiên của tập kết quả được chỉ định bằng một truy vấn như sau:(chưa được kiểm tra)

SELECT m.empcode     AS `EmpCode` 
     , m.name        AS `EmpName`
     , m.dept        AS `Department`
     , d.dt          AS `AbsentDate`
  FROM ( SELECT DATE(t.s_date) AS dt
           FROM emp_tx t
          WHERE t.s_date >= '2012-12-12' 
            AND t.s_date < DATE_ADD( '2012-12-20' ,INTERVAL 1 DAY)
          GROUP BY DATE(t.s_date)
          ORDER BY DATE(t.s_date)
       ) d
 CROSS
  JOIN master m
  LEFT
  JOIN emp_tx p
    ON p.s_date >= d.dt
   AND p.s_date <  d.dt + INTERVAL 1 DAY
   AND p.empcode = m.empcode
 WHERE p.empcode IS NULL
 ORDER
    BY m.empcode
     , d.dt

Lấy cột thứ năm đó TotalNoofAbsent được trả về trong cùng một tập kết quả là có thể, nhưng nó sẽ làm cho truy vấn đó thực sự lộn xộn. Chi tiết này có thể được xử lý hiệu quả hơn ở phía máy khách, khi xử lý tập kết quả trả về.

Cách hoạt động của truy vấn

Chế độ xem nội tuyến có bí danh là d cung cấp cho chúng tôi một tập hợp các giá trị "ngày tháng" mà chúng tôi đang kiểm tra. Sử dụng emp_tx bảng làm nguồn của các giá trị "ngày tháng" này là một cách thuận tiện để thực hiện việc này. Không phải là DATE() hàm chỉ trả về phần "ngày tháng" của đối số DATETIME; chúng tôi đang sử dụng GROUP BY để có được danh sách ngày tháng riêng biệt (tức là không có giá trị trùng lặp). (Những gì chúng tôi đang theo đuổi, với truy vấn chế độ xem nội tuyến này, là một tập hợp các giá trị DATE riêng biệt giữa hai giá trị được chuyển vào dưới dạng đối số. Có nhiều cách khác, liên quan hơn, để tạo danh sách các giá trị DATE.)

Miễn là mọi giá trị "ngày" mà bạn sẽ coi là "vắng mặt" xuất hiện ở đâu đó trong bảng (nghĩa là, ít nhất một empcode có một giao dịch vào mỗi ngày được quan tâm) và miễn là số hàng trong emp_tx bảng không quá mức, khi đó truy vấn chế độ xem nội tuyến sẽ hoạt động hợp lý.

(LƯU Ý:Truy vấn trong chế độ xem nội tuyến có thể được chạy riêng, để xác minh rằng kết quả là chính xác và như chúng tôi mong đợi.)

Bước tiếp theo là lấy kết quả từ chế độ xem nội tuyến và thực hiện CROSS JOIN hoạt động (để tạo ra một sản phẩm Descartes) để khớp với MỌI empcode với MỌI date được trả về từ chế độ xem nội tuyến. Kết quả của thao tác này thể hiện mọi trường hợp "tham dự" có thể xảy ra.

Bước cuối cùng trong truy vấn là thực hiện thao tác "chống tham gia", sử dụng LEFT JOINWHERE IS NULL Thuộc tính. LEFT JOIN (nối ngoài) trả về mọi lần xuất hiện tham dự có thể có (từ phía bên trái), BAO GỒM những trường hợp không có hàng phù hợp (bản ghi tham gia) từ emp_tx bảng.

"Thủ thuật" là bao gồm một vị từ (trong mệnh đề WHERE) loại bỏ tất cả các hàng nơi tìm thấy bản ghi tham dự phù hợp, để những gì chúng ta còn lại là tất cả các kết hợp của empcodedate (các trường hợp tham dự có thể xảy ra) khi KHÔNG có giao dịch tham dự MATCHING.

(LƯU Ý:Tôi đã cố ý để các tham chiếu đến cột s_date (DATETIME) "trống" trong các vị từ và các vị từ phạm vi đã sử dụng. Điều này sẽ cho phép MySQL sử dụng hiệu quả một chỉ mục thích hợp bao gồm cột đó.)

Nếu chúng ta bọc các tham chiếu cột trong các vị từ bên trong một hàm, ví dụ:DATE(p.s_date) , thì MySQL sẽ không thể sử dụng hiệu quả một chỉ mục trên s_date cột.

Như một trong những nhận xét (về câu hỏi của bạn) đã chỉ ra, chúng tôi không phân biệt bất kỳ sự phân biệt nào giữa các giao dịch đánh dấu một nhân viên là "đến" hay "đi ra ngoài". Chúng tôi CHỈ tìm kiếm sự tồn tại của một giao dịch cho mã trống đó trong khoảng thời gian 24 giờ nhất định "từ nửa đêm đến nửa đêm".

Có những cách tiếp cận khác để có được cùng một tập hợp kết quả, nhưng kiểu "chống nối kết" thường mang lại hiệu suất tốt nhất với các tập hợp lớn.

Để có hiệu suất tốt nhất, bạn có thể muốn bao gồm các chỉ mục:

... ON master (empcode, name, dept)

... ON emp_tx (s_date, empcode)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cập nhật MySQL với lựa chọn phụ

  2. Nhiều mối quan hệ hấp dẫn giống hệt nhau

  3. com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:trong mysql

  4. Đổi tên bảng Amazon RDS thành lỗi ném chữ hoa

  5. Không thể cài đặt flask-sqlalchemy mysql-python