【问题标题】:Find the lowest score after the first Highest Score在第一个最高分之后找到最低分
【发布时间】:2020-08-11 21:19:10
【问题描述】:

我正在寻找一个 SQL 查询。

表 1:源表

表 2:结果表

附上病人桌。在这里,我想找到每个患者的最高分、最高分日期、最低分和最低分日期。棘手的部分是,如果患者在两个不同的日期(10/5/2018 和 8/4/2020)具有相同的最高分(这里是 9),我们需要取最早的高分(10/5/2018) .同样,如果患者在两个不同日期(2019 年 3 月 1 日和 2020 年 4 月 2 日)的最低分相同(此处为 6),我们应该取最新的低分(2020 年 4 月 2 日)

表 1:源表包含单个患者的所有分数。患者 ID 是该表的主键。我想要一个看起来像表 2 的结果表。

我试过了

SELECT distinct
    pat.PAT_NAME 'Patient Name'
    , pat.PAT_ID
    , CAST(pat.CONTACT_DATE AS DATE) 'Service Date'
    , pat.MEAS_VALUE 'Score'
    , [Row Number] = rank() OVER (PARTITION BY pat.PAT_ID ORDER BY CAST(pat.MEAS_VALUE AS int) DESC, CONTACT_DATE asc)
FROM Patient pat            
WHERE pat.PAT_ID = 'A112233'

但是这段代码可以显示我最高或最低的分数。但这并不能满足我的所有要求。

【问题讨论】:

  • 1.请将数据显示为格式化文本 - 而不是图像(最好是 DDL/DML 语句)。 2. 请向我们展示您的尝试 - SO 不是代码编写服务。

标签: sql sql-server


【解决方案1】:

如果表 t 包含以下列:PatientName、PatientID、ServiceDate、Score。像这样的:

;with high_low_cte(PatientID, high_rn, low_rn) as(
    select
      PatientID,
      row_number() over (partition by PatientID order by Score, ServiceDate asc),
      row_number() over (partition by PatientID order by Score, ServiceDate desc)
    from
      t)
select * from high_low_cte where high_rn=1 and low_rn=1;

更新问题后:

;with high_low_cte([Patient Name], PAT_ID, [Service Date], Score, high_rn, low_rn) as (
    SELECT distinct
      pat.PAT_NAME 'Patient Name'
      ,pat.PAT_ID
      ,CAST(pat.CONTACT_DATE AS DATE) 'Service Date'
      ,pat.MEAS_VALUE 'Score'
      ,high_rn=row_number() OVER (PARTITION BY pat.PAT_ID ORDER BY CAST(pat.MEAS_VALUE AS int) DESC, CONTACT_DATE asc) 
      ,low_rn=row_number() OVER (PARTITION BY pat.PAT_ID ORDER BY CAST(pat.MEAS_VALUE AS int) asc, CONTACT_DATE asc) 
    FROM  
      Patient pat                                 
    WHERE                  
    pat.PAT_ID='A112233')
select hld1.*, hld2.Score [Low_Score], hld2.[Service Date] [Low Service Date]
from high_low_cte hld1 join high_low_cte hld2 on hld1.PAT_ID=hld2.PAT_ID
where
  hld1.high_rn=1
  and hld2.low_rn=1;

【讨论】:

  • 谢谢史蒂夫。我已经尝试过这种方法,但我想根据某些条件找到最高和最低分数。在这里,我想找到每个患者的最高分、最高分日期、最低分和最低分日期。棘手的部分是,如果患者在两个不同的日期(10/5/2018 和 8/4/2020)具有相同的最高分(这里是 9),我们需要取最早的高分(10/5/2018) .同样,如果患者在两个不同的日期(2019 年 3 月 1 日和 2020 年 4 月 2 日)的最低分相同(此处为 6),我们应该取最新的低分(2020 年 4 月 2 日)
  • 谢谢史蒂夫。这非常有效。我做的唯一一件小事是通过 Low_rn 中的 desc 订购 contact_Date 以找到最新的低分。除了它是完美的。也非常感谢所有回答的人......
【解决方案2】:

您可以通过row_number() 使用条件聚合:

select PatientName, PatientID, 
       min(case when ;
_hi = 1 then ServiceDate end) as high_date,
       max(score) as high_score,
       min(case when seqnum_lo = 1 then ServiceDate end) as low_date,
       min(score) as low_score
from (select t.*
             row_number() over (partition by PatientID order by Score desc, ServiceDate asc) as seqnum_hi,
             row_number() over (partition by PatientID order by Score, ServiceDate desc) as seqnum_lo
      from t
     ) t
group by PatientName, PatientID;

【讨论】:

    【解决方案3】:

    首先,得到最高分和最低分,然后找出它发生在哪一天

    ;with scores as (  -- get highest/lowest score per patientId
       select patientID, max(score) hScore, min(score) lScore 
       from table
       group by patientID
    ), dates as (
       -- get first date a patient had the highest score
       select patientID, min(ServiceDate) dateHScore, score
       from table t
       inner join scores s on s.patientid = t.patientid and s.hScore= t.score
       group by patientID, score
       union all
       -- get the last date a patient had the lowest score
       select patientID, max(ServiceDate) dateLScore, score
       from table t
       inner join scores s on s.patientid = t.patientid and s.lScore = t.score
       group by patientID, score
    )
    select t.patientName, scores.*
    from table t
    inner join scores s on s.patientid= t.patientid
    

    如果您想在同一行的不同列上获得最高/最低分,只需拆分第二个 cte 并在选择中适当地加入它们

    【讨论】:

    • 如果一次访问就可以查询同一个表 3 次通常不是一个好主意。
    【解决方案4】:

    我还没有测试过,但也许像这样的东西可以完成这项工作:

    select x.PatientName, x.PatientId,
      case when x.HSD=1 then 'Highest' else 'Lowest' as ScoreType,
      Score, ScoreDate
    from (
      select
        p.PAT_NAME as PatientName,
        p.PAT_ID as PatientId,
        p.MEAS_VALUE as Score,
        p.CONTACT_DATE as ScoreDate,
        row_number() over (partition by p.PatientId order by p.MEAS_VALUE desc, p.CONTACT_DATE desc) as HSD,
        row_number() over (partition by p.PatientId order by p.MEAS_VALUE asc, p.CONTACT_DATE asc) as LSD
      from Patient p
      ) x
    where 
      x.HighestScore=1 or
      x.LowestScoreDate=1
    

    您应该收到两行。您需要对数据进行透视才能获得预期的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 2021-01-18
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多