如何确定列值是否在日期范围内来回更改?

时间:2018-02-19 19:15:22

标签: sql distinct ingres

背景

我们有一个工作查询,用于选择患者(d8_5_B.xpostaccessuse)患者(任何表格中的xpid列)在他们约会后90天内使用的访问类型(d1.ddiadate +'90 days') 变得慢性(SELECT d8_B.start_date, d8_5_B.xpostaccessuse FROM d1 LEFT JOIN d8 d8_B ON d1.xpid = d8_B.xpid LEFT JOIN d8_5 d8_5_B ON d8_B.xsession_id = d8_5_B.xsession WHERE d8_B.start_date IN ( SELECT MAX(d8.start_date) FROM d8 LEFT JOIN d1 ON d8.xpid = d1.xpid WHERE d8.start_date <= d1.ddiadate + '90 days' GROUP BY d8.xpid ) )。输出是两列:一个日期,一个整数。

查询:

d8_5_B.xpostaccessuse = 3

目标:

我们需要能够确定他们的访问权限是否在这90天期间来回变化。理想情况下,我们也希望能够突出显示切换到的内容以及何时切换,但较小的胜利仍然有用。

  • 我们知道d1.ddiadate上的d8_5_B.xpostaccessuse = 3
  • 我们知道d1.ddiadate +'90 days'上的3

但是,如果他们的访问权限从5更改为3并在此90天范围内再次更改为3,我们无法确定其不是{{1}一直以来。

我们如何确定:

  • 如果值从3更改为其他内容并返回3 在这90天期间?
  • 改变了什么,何时改变?

到目前为止工作:

到目前为止,我们最好的想法是使用count()聚合来计算日期范围内的总行数,然后计算d8_5_B.xpostaccessuse = 3的行数并比较结果。这将告诉我们是否存在不连续性,即使它不是什么。我们无法使用此方法,主要是由于所需的group by

我们的另一个想法是尝试选择不同的值d8_5_B.xpostaccessusegroup by xpid,但同样的问题出现在group by上。

更新

  • Ingres 9
  • 打开“什么时候”部分的建议。我想象的可能是每个列的列,它在中间的变化以及变化开始的日期。如果患者多次进行访问更改,这显然会变得棘手,但这种情况不应经常发生。目前,报告额外的行是可以接受的,除非有人想到更优雅的解决方案。
  • 样本表(以下为G琼斯):

    create table d1
    (xpid integer, ddiadate ingresdate);
    
    create table d8
    (xpid integer, xsession_id integer, start_date ingresdate);
    
    create table d8_5
    (xpid integer, xsession integer, xpostaccessuse integer);
    
    insert into d1 values(1, '2018-01-01');
    insert into d1 values(2, '2018-01-01');
    
    insert into d8 values(1, 1, '2018-01-01');
    insert into d8 values(1, 2, '2018-01-10');
    insert into d8 values(1, 3, '2018-01-20');
    
    insert into d8 values(2, 1, '2018-01-01');
    insert into d8 values(2, 2, '2018-01-10');
    insert into d8 values(2, 3, '2018-01-20');
    
    insert into d8_5 values(1, 1, 3);
    insert into d8_5 values(1, 2, 3);
    insert into d8_5 values(1, 3, 3);
    
    insert into d8_5 values(2, 1, 3);
    insert into d8_5 values(2, 2, 5);
    insert into d8_5 values(2, 3, 3);
    
  • 与此任务相关的表格定义:

    d1:人口统计表/基本患者信息

    • 患者ID&amp;表索引(d1.xpid
    • Date First Chronic(d1.ddiadate

    d8:会话表

    • 会话ID&amp;表索引(d8.xsession_id
    • 患者ID(d8.xpid
    • 会话开始日期时间(d8.start_date

    d8_5:具有访问数据的会话子表

    • 会话ID&amp;表索引(d8_5.xsession
    • 患者ID(d8_5.xpid
    • 访问类型(d8_5.xpostaccessuse

    请注意,所有三个表都可以在xpidd8.xsession_id = d8_5.xsession

  • 上加入

3 个答案:

答案 0 :(得分:1)

您可能需要select COUNT(DISTINCT d8_5_B.xpostaccessuse)后使用group by来显示患者的状态。

如果您想要完整的请求,请提供数据测试和创建表;)

编辑:

这可能会显示90天内的不同访问次数(我使用INNER JOIN,因为看起来你的左边没用了)

SELECT
    d8.start_date,
    d5.xpostaccessuse,
    d1.access_count
FROM (
    SELECT 
        d8.xpid, 
        MAX(d8.start_date) date_max, 
        COUNT(DISTINCT d5.xpostaccessuse) access_count
    FROM d8
    INNER JOIN d1 
        ON d8.xpid = d1.xpid 
    INNER JOIN d8_5 d5 
        ON d8.xsession_id = d5.xsession
    WHERE 
        d8.start_date > d1.ddiadate 
        AND d8.start_date <= d1.ddiadate + '90 days'
    GROUP BY d8.xpid
) d1 
INNER JOIN d8 
    ON d1.xpid = d8.xpid
    AND d8.start_date = d1.date_max
INNER JOIN d8_5 d5 
    ON d8.xsession_id = d5.xsession

答案 1 :(得分:1)

由于这里提到了Ingres,一种可能的方法可能是使用行生成数据库过程来识别哪些行没有改变,并避免返回任何您不感兴趣的行。示例如下所示关于我对表格的看法,希望它有一些用处。

-- Some sample data.

create table d1
(xpid integer, ddiadate ingresdate);

create table d8
(xpid integer, xsession_id integer, start_date ingresdate);

create table d8_5
(xpid integer, xsession integer, xpostaccessuse integer);

insert into d1 values(1, '2018-01-01');
insert into d1 values(2, '2018-01-01');

insert into d8 values(1, 1, '2018-01-01');
insert into d8 values(1, 2, '2018-01-10');
insert into d8 values(1, 3, '2018-01-20');

insert into d8 values(2, 1, '2018-01-01');
insert into d8 values(2, 2, '2018-01-10');
insert into d8 values(2, 3, '2018-01-20');

insert into d8_5 values(1, 1, 3);
insert into d8_5 values(1, 2, 3);
insert into d8_5 values(1, 3, 3);

insert into d8_5 values(2, 1, 3);
insert into d8_5 values(2, 2, 5);
insert into d8_5 values(2, 3, 3);

-- Query to show patient's access type at each session
-- during the 3 months before becoming chronic.

select d1.xpid, d8.start_date, d8_5.xpostaccessuse
from d1
join d8 on d1.xpid = d8.xpid
join d8_5 on d1.xpid = d8_5.xpid and d8.xsession_id = d8_5.xsession
where d8.start_date <= d1.ddiadate + '90 days'
and d8.start_date >= d1.ddiadate
order by xpid, start_date;

-- Use a row-producing database procedure, based on the
-- above query, to return a row only when data changes.

create procedure rpp
result row r (xpid integer, start_date date, xpostaccessuse integer) =
declare
  xpid = integer;
  sd = ingresdate;
  xp = integer;
  xplast = integer;
  xpidlast = integer;
begin
  xplast = -1; xpidlast = -1;
  for
  select d1.xpid, d8.start_date, d8_5.xpostaccessuse
  into :xpid, :sd, :xp
  from d1
  join d8 on d1.xpid = d8.xpid
  join d8_5 on d1.xpid = d8_5.xpid and d8.xsession_id = d8_5.xsession
  where d8.start_date <= d1.ddiadate + '90 days'
  and d8.start_date >= d1.ddiadate
  order by xpid, d8.start_date desc
  do
    if :xplast != :xp or :xpidlast != :xpid
    then
      return row(:xpid, :sd, :xp);
      xplast = :xp;
      xpidlast = :xpid;
    endif;
  endfor;
end;

-- Query the row-producing procedure.

select * from rpp() order by xpid, start_date;

答案 2 :(得分:0)

在这种SQL风格中,Ingres 9(已经过时,可能与Internet的其余部分无关,但是如果不是……),则在哪里可以使用子查询存在很多限制。

我最终为需要放置在“非法”位置的子查询创建视图,将这些视图作为表加入并获得相同的效果。

祝你好运!