【问题标题】:PostgreSQL Cursor to update tablePostgreSQL 游标更新表
【发布时间】:2016-10-08 14:04:08
【问题描述】:

我有一个代表患者体检的表格,它有检查的 ID 和患者 ID。

我想逐行遍历表格并获取每个患者 ID 并比较其不同的咨询,看看它是否被视为“新攻击”。我正在处理疟疾疾病,我们认为在过去 60 天内接受过咨询并且对测试呈阳性的每个患者都是老病例和new_attack = false,否则new_attack = true

但是当我浏览表格时,我必须考虑到 palufalci 列,因为患者可以进行体检但对疟疾检测不呈阳性,在这种情况下为 new_attack = false

创建表的代码如下:

CREATE TABLE public.tbl_diagnostiques_guy (
  id integer NOT NULL DEFAULT nextval('tbl_diagnostiques_guy_id_seq'::regclass),
  dateconsultation date,
  numeropatient character varying(13),
  palufalci boolean,
  new_attack boolean
);

我用这个查询计算了每位患者两次体检之间的datediff

SELECT id, numeropatient, palufalci,
    dateconsultation, NextDate,
    date(NextDate) - date(dateconsultation) as Diff, new_attack
FROM (
  SELECT id, numeropatient, palufalci, dateconsultation, new_attack,
         (SELECT  MIN(dateconsultation) 
          FROM    tbl_diagnostiques_guy T2
          WHERE   T2.numeropatient = T1.numeropatient
          AND     T2.dateconsultation > T1.dateconsultation
         ) AS NextDate
  FROM tbl_diagnostiques_guy T1) AS T
WHERE NextDate IS NOT NULL AND (date(NextDate) - date(dateconsultation) < 60)
GROUP BY id, numeropatient, palufalci, dateconsultation, NextDate, new_attack
ORDER BY numeropatient DESC;

结果是: here

现在我想知道如何更新表格并获得我想要的结果。

【问题讨论】:

  • tbl_diagnostiques_guy 是否有列palufalcivivax?该查询似乎建议前者,但您的表定义具有后者。请编辑您的问题(请参阅问题标签下的链接),然后将输出的文本版本(导出到 PgAdminIII 中的文件)而不是图形链接。
  • 您好,首先我要感谢您编辑我的帖子。这是palufalci,我编辑了这个问题。
  • 你好阿纳斯,欢迎来到 SO。请看下面我的回答。祝你的数据库和研究好运,我自己患过两次疟疾,所以继续努力吧!

标签: postgresql cursor datediff


【解决方案1】:

从您的问题看来,您想用值填充 new_attack 列。这很容易通过您的查询完成 - 尽管您设置 new_attack 值的逻辑似乎缺失 - 但实际上使用 lag() window function 有一种更优雅的形式:

SELECT id, numeropatient, palufalci, dateconsultation,
       CASE WHEN days IS NULL OR days > 60 THEN false
       ELSE palufalci AND old_test
       END AS new_attack
FROM (
  SELECT id, numeropatient, palufalci, lag(palufalci) OVER w AS old_test,
         dateconsultation, dateconsultation - lag(dateconsultation) OVER w AS days,
  FROM tbl_diagnostiques_guy
  WINDOW w AS (PARTITION BY numeropatient ORDER BY dateconsultation) ) sub;

运行该语句以验证它是否符合您的预期。如果满意,那么您可以轻松地将整个内容修改为 UPDATE 声明:

UPDATE tbl_diagnostiques_guy t
SET new_attack =
       CASE WHEN days IS NULL OR days > 60 THEN false
       ELSE palufalci AND old_test
       END
FROM (
  SELECT id, numeropatient, palufalci, lag(palufalci) OVER w AS old_test,
         dateconsultation, dateconsultation - lag(dateconsultation) OVER w AS days,
  FROM tbl_diagnostiques_guy
  WINDOW w AS (PARTITION BY numeropatient ORDER BY dateconsultation) ) sub
WHERE t.id = sub.id; -- add other join conditions as required

让我们更详细地看一下new_attack 逻辑:

CASE WHEN days IS NULL OR days > 60 THEN false
ELSE palufalci AND old_test
END

第一行WHEN days IS NULL OR days &gt; 60 THEN false表示:如果上一次咨询是60天前或者这是第一次咨询(lag()函数会返回NULL为第一次咨询,因为没有上一行),那么new_attack 的值为false

第二行palufalci AND old_test 的意思是:如果在 60 天内进行了第二次咨询,那么 new_attacktrue,前提是之前和当前的测试都是 true

【讨论】:

  • 您的回答提供了我正在寻求的解决方案的 70%。我认为这是我的错,因为我没有提到如果我们有新的咨询,我们必须将它与之前的 new_attack=true 进行比较。首先,我们将所有患者的所有第一次咨询设为 new_attack=true,然后将之后的咨询与 new_attack=true 进行比较。
  • 添加一些其他规则后工作正常,谢谢帕特里克
猜你喜欢
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 2011-07-17
相关资源
最近更新 更多