Crazy code transformation

The function requirement is to
   count the specified month of employees: the number of employees, the number of employees who have joined, the number of employees who have left, and the number of employees in the previous month.

Original design
   bj_worker: employee table.
   bj_worker_change: employee entry and exit log table, a record will be added for each entry and exit, and entry and exit are distinguished by status
    Entry_flag: entry flag
    dimission_flag: resignation flag
    change_date: entry or resignation date

" Crazy type" code implementation (assuming the statistical month is 2016-10) 

   SELECT
  (
    (SELECT
      COUNT(id)
    FROM
      bj_worker_change t
    WHERE t.change_date <= '20161031'
      AND t.entry_flag = 1
      AND t.worker_type = b.worker_type
      AND t.company_id = b.company_id) -
    (SELECT
      COUNT(id)
    FROM
      bj_worker_change t
    WHERE t.change_date <= '20161031'
      AND t.dimission_flag = 1
      AND t.worker_type = b.worker_type
      AND t.company_id = b.company_id)
  ) AS current_month_num,<=number of employees in the current month
  (SELECT
    COUNT(id)
  FROM
    bj_worker_change t
  WHERE t.change_date <= '20161031'
    AND t.change_date >= '20161001'
    AND t.entry_flag = 1
    AND t.worker_type = b.worker_type
    AND t.company_id = b.company_id) AS current_add_num,<=number of employees this month
  (SELECT
    COUNT(id)
  FROM
    bj_worker_change t
  WHERE t.change_date <= '20161031'
    AND t.change_date >= '20161001'
    AND t.dimission_flag = 1
    AND t.worker_type = b.worker_type
    AND t.company_id = b.company_id) AS current_js_num,<=number of employees leaving this month
  (
    (SELECT
      COUNT(id)
    FROM
      bj_worker_change t
    WHERE t.change_date <= '20160931'
      AND t.entry_flag = 1
      AND t.worker_type = b.worker_type
      AND t.company_id = b.company_id) -
    (SELECT
      COUNT(id)
    FROM
      bj_worker_change t
    WHERE t.change_date <= '20160931'
      AND t.dimission_flag = 1
      AND t.worker_type = b.worker_type
      AND t.company_id = b.company_id)
  ) AS last_month_num <= number of employees last month
FROM
  bj_worker_change b


Problem Analysis

  Symptom Analysis

  (1) SQL is too complex: the development workload is large, prone to errors, and subsequent maintenance is difficult;
  (2) The execution efficiency is too slow: the SQL is complex, the database pressure is high, and the execution efficiency is also very slow;

  the crux of the

     table structure design Unreasonable: bj_worker_change is an operation flow meter. The operation of personnel entry and exit corresponds to a record. The entry and exit operation causes the status change of the business entity (bj_worker), that is, the historical work status information of bj_worker, but this bj_worker historical work is missing from the original design. The status table needs to be analyzed in real time when the employee's historical work status is obtained, resulting in the complexity of the module code and low efficiency .

The solution is to
add the bj_worker_duty table to record the user history on the date of departure. The structure is as follows:
  bj_worker_duty
   ●id
   ●worker_id
   ●entry_date: date of entry
   ●departure_date: date of departure (default is 99999999, change when adding departure)
   The program needs to be modified accordingly :
   (1) According to the bj_woker_change record, use the program or stored procedure to generate the initialization record of bj_worker_change;
   (2) When inserting the bj_worker_change table, maintain the record of the bj_worker_duty table at the same time.
 
  SQL transformation is as follows
     
 SELECT
    SUM(CASE WHEN d.`entry_date`<='201610' AND d.`departure_date` >=  '201610'   
        THEN 1 ELSE 0 END) AS current_month_num,
    SUM(CASE WHEN d.`entry_date`>='20161000' AND d.`entry_date` <=  '20161099'
        THEN 1 ELSE 0 END) AS current_add_num,
    SUM(CASE WHEN d.`departure_date`>='20161000' AND d.`departure_date` <=  '20161099'
        THEN 1 ELSE 0 END) AS current_sj_num,
    SUM(CASE WHEN d.`entry_date`<='201609' AND d.`departure_date` >=  '201609'
        THEN 1 ELSE 0 END) AS last_month_num
     FROM bj_worker_duty d;

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326571452&siteId=291194637