从SQL表中有效识别出任何8周内n> 3个日期的所有FK项目?

时间:2015-03-07 18:29:04

标签: sql sql-server

我有一个~400,000行表,其中包含约30,000人收集约会的日期。每行都有患者ID号和约会日期。我想有效地选择在8周内至少有4次约会的人。理想情况下,我也会标记这8周内的约会。我在不允许CLR聚合函数的服务器环境中工作。这可以在SQL服务器中执行吗?如果是这样,怎么样?

我曾经想过:

  • 如果我可以通过GROUP BY编写我自己的聚合函数来实现这一点,这显然是最好的 - 但我似乎无法通过内置聚合函数找到任何方法。
  • 我可以在原始表格中添加一个列,给出任何给定约会8周后的日期,但不能提出任何不涉及for循环然后询问问题行的方法按行,该窗口内是否至少有3个其他约会。
  • 最后,即使我可能只做GROUP BY,但不知何故创建了100个新列(因为某些患者可以进行多次约会)来创建一个包含患者索引的每个约会的表格但是,即使作为SQL新手,我也很确定,只要我想到添加100个新列,我就会走错路......

为了清楚讨论,这里有一些符号:

MyTable的:

ApptID    PatientID    ApptDate (in smalldatetime)
--------------------------------------------------
Apt1       Pt1          Datetime1
Apt2       Pt1          Datetime2
Apt3       Pt2          Datetime3
...       ...          ...

期望的输出(一个选项):

PatientID    4aptsIn8weeks? (Boolean)  InitialApptDateForWin
Pt1          1                         Datetime1
Pt2          0                         NULL
Pt3          1                         Datetime3
...

期望的输出(另一种选择):

ApptID     PatientID    ApptDate     InAn8wkWindow?   InitialApptDateForWin
Apt1       Pt1          Datetime1    1                Datetime1
Apt2       Pt1          Datetime2    1                Datetime1
Apt3       Pt2          Datetime3    0                NULL
...       ...          ...

但实际上,任何最终让我选择符合此标准的患者和约会的输出格式都会花花公子....

感谢您的任何想法!


编辑:这里有一个略微解压缩的下面我选择的答案的实现大纲,以防万一细节对其他人有用(对SQL很新,我花了几个小时才能让它工作):

WITH MyTableAlias AS (
    SELECT * FROM MyTable
    )
SELECT MyTableAlias.PatientID, MyTable.Apptdate AS V1, 
    MyTableAlias.Apptdate AS V2
INTO temp1
FROM MyTable INNER JOIN MyTableAlias
ON (
   MyTable.PatientID = MyTableAlia.PatientID 
   AND (DATEDIFF(Wk,MyTable.Apptdate,MyTableAlias.Apptdate) <=8 )
   );

-- Since this gives for any given two visit dates 3 hits 
-- (V1-V1, V1-V2, V2-V2), delete the ones where the second visit is being 
-- selected as V1:
DELETE FROM temp1
WHERE V2<V1;

-- So far we have just selected pairs of visits within an 8 week
-- span of each other, including an entry for each visit being 
-- within 8 weeks of itself, but for the rest only including the item
-- where the second visit is after the first.  Now we want to look 
-- for examples of first visits where there are at least 4 hits:
SELECT PatientID, V1, MAX(V2) AS lastvisitinspan, DATEDIFF(Wk,V1,MAX(V2))
    AS nWeeksInSpan, COUNT(*) AS nWeeksInSpan
INTO MyOutputTable
FROM temp
GROUP BY PatientID, V1
HAVING COUNT(*)>3;

-- From here on it's just a matter of how I want to handle patients with two        
-- separate V1 examples meeting criteria...

1 个答案:

答案 0 :(得分:0)

查询的粗略轮廓:

  • INNER将表(“table”)与其自身(“别名”)连接起来,ON子句将是:
    • table.patientid = alias.patientid
    • table.appointment_date&lt; alias.appointment_date
    • datediff(table.appointment_date,alias.appointment_date)&lt; = 8周
  • 然后GROUP BY table.patientid,table.appointment_date
  • 输出table.patientid,table.appointment_date,MAX(alias.appointment_date),COUNT(*)
  • 添加HAVING COUNT(*)&gt; n条款

但是有一些问题:

  1. 有400,000行,JOIN可以产生非常大的结果集
  2. 它会计算两次日期范围。例如。如果在9周内有4次访问,那么它将返回两行(#1,#2,#3和#2,#3,#4)。