我在医院里有一张床单,如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
解决这个问题的最佳方法是什么?
答案 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以获得预期结果