繁体   English   中英

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

[英]Efficiently identify all FK items with n>3 dates within any 8 week period from a SQL table?

我有一个~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...

查询的粗略轮廓:

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

但是有一些问题:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM