MySQL:根据两列之间的条件组合表中行的数据

时间:2018-02-03 02:30:03

标签: mysql join

我在医院里有一张床单,如MySql

patient_id      date_started     date_stopped

1               2018-01-10       2018-01-15
1               2018-01-15       2018-01-28
1               2018-01-28       2018-02-05
2               2018-01-15       2018-02-10
2               2018-03-05       2018-04-12
3               2018-01-10       2018-01-20
3               2018-01-20       null
4               2018-02-10       2018-02-10

现在我不希望那些患者的date_stopped与另一行的date_started相同。我希望输出像

patient_id     date_started     date_stopped

1              2018-01-10       2018-02-05
2              2018-01-15       2018-02-10
2              2018-03-05       2018-04-12
4              2018-02-10       2018-02-10

如果我做INNER JOIN,我会得到多行

SELECT
  *
FROM bed AS bed_1
INNER JOIN bed_2
  ON bed_2.patient_id = bed_1.patient_id
  AND bed_2.date_started != bed_2.date_stopped

解决这个问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

可以通过编写接受的程序来完成 patient_id和date_stopped并递归,直到date_stopped不等于同一患者的下一个date_started

CREATE PROCEDURE FINAL_STOP_DATE(IN patientId INT,IN dateStopped DATETIME, OUT finalStopDate DATETIME)
 +  BEGIN
 +    DECLARE current_patient INT;
 +    DECLARE curr_start_date DATETIME;
 +    DECLARE curr_stop_date DATETIME;
 +    SET max_sp_recursion_depth = 250;
 +    SELECT patient_id,
 +      date_started,date_stopped
 +    INTO current_patient,curr_start_date,curr_stop_date
 +    FROM bed
 +          WHERE patient_id = patientId AND date_started = dateStopped
 +    LIMIT 1;
 +    if current_patient = patientId  AND curr_start_date = dateStopped THEN
 +      CALL FINAL_STOP_DATE(current_patient, curr_stop_date, finalStopDate);
 +    ELSE
 +      SET finalStopDate = dateStopped;
 +    END IF ;
 +  END; 

因此,此程序的输出是给定患者的最终停止日期,不包括中途所有连续的开始和停止日期

我们可以为床表中的每个记录调用此过程,并选择此过程的输出作为date_ended列。为了实现这一点,我们需要编写一个中介函数,因为我们无法从SQL中的select子句调用过程

CREATE FUNCTION GET_FINAL_STOP_DATE(patientId INT, date_stopped DATETIME)
 +  RETURNS DATETIME
 +  BEGIN
 +    DECLARE final_stop_date DATETIME;
 +    CALL FINAL_STOP_DATE(patientId, date_stopped, final_stop_date);
 +    RETURN final_stop_date;
 +  END; 

现在从select子句调用此函数,它将选择返回值作为date_ended列现在在结果集上执行GROUP BY patient_id,date_ended并选择MIN date_started

SELECT patient_id, 
       MIN(date_started),
       GET_FINAL_STOP_DATE(patient_id,date_stopped) AS date_ended
FROM bed
GROUP BY patient_id, date_ended

最终结果将是

patient_id     date_started     date_ended

1              2018-01-10       2018-02-05
2              2018-01-15       2018-02-10
2              2018-03-05       2018-04-12
3              2018-01-10       null
4              2018-02-10       2018-02-10

最后,添加一个where条件,说date_ended不应为null以获得预期结果