【问题标题】:Choosing MAX value by id in a view?在视图中通过 id 选择 MAX 值?
【发布时间】:2021-04-26 17:17:25
【问题描述】:

我已经根据我们数据库中的几列创建了一个简单的视图

ALTER VIEW [BI].[v_RCVLI_Test] AS
Select distinct
    Borger.CPRnrKort as CPR,
    (...)
    IndsatsDetaljer.VisitationId as VisitationsId,
    Indsats.KatalogNavn as IndsatsNavn,
    (case
        when 
        (   
            Indsats.Model = 'SMDB2 Tilbudsmodel' or
            Indsats.Model = 'SMDB2 Samtalemodel' or
            Indsats.Model = 'Tilbudsmodel' or
            Indsats.Model = 'NAB Tilbudsmodel'
        )
        then IndsatsDetaljer.ServicePeriodeStart
        else IndsatsDetaljer.Ikrafttraedelsesdato
        end
    ) as StartDato,
    (case
        when 
        (   
            Indsats.Model = 'SMDB2 Tilbudsmodel' or
            Indsats.Model = 'SMDB2 Samtalemodel' or
            Indsats.Model = 'Tilbudsmodel'
        )
        then (case when IndsatsDetaljer.VisitationSlut = '9999-12-31' then convert(varchar(10), getdate(), 23) else IndsatsDetaljer.VisitationSlut end)
        when
        Indsats.Model = 'NAB Tilbudsmodel'
        then (case when IndsatsDetaljer.NABehandlingSlutDato = '9999-12-31' then convert(varchar(10), getdate(), 23) else IndsatsDetaljer.NABehandlingSlutDato end)
        else (case when IndsatsDetaljer.VisitationSlut = '9999-12-31' then convert(varchar(10), getdate(), 23) else IndsatsDetaljer.VisitationSlut end)
        end
    ) as StopDato,
    Refusion.Handlekommune as Handlekommune,
    replace(Refusion.Betalingskommune, 'Ukendt', 'Kendt') Betalingskommune

from nexus2.Fact_VisiteretTid as Fact

join nexus2.Dim_Paragraf Paragraf
on Fact.DW_SK_Paragraf = Paragraf.DW_SK_Paragraf
join nexus2.Dim_Indsats Indsats
on Fact.DW_SK_Indsats = Indsats.DW_SK_Indsats (...)

存在 StartDato 和 StopDato 的情况是因为这些日期来自不同的列。我已经将日期 '9999-12-31' 转换为当前日期,因为我们稍后会进行一些时间计算,这样更方便。

CPR 是一个人的 id,VisitationsId 是这个人接受的服务的 id。 理论上,每个 VisitationsId 应该只有一个 StartDato 和一个 StopDato,但是由于文档系统的故障,我们有时会得到两个 StopDato:一个是正确的,一个是 '9999-12-31'(现在转换为当前日期)。

所以我需要按 VisitationsId 分组,然后只取 StopDato 的 MIN 值,但我有点不确定如何去做?

CPR VisitationsId StartDato StopDato Something Else
123 56 2019-01-01 2019-12-12 Something
123 56 2019-01-01 9999-12-31 Something
123 58 2019-01-01 2019-12-14 Something
345 59 2018-11-01 9999-12-31 Something
345 55 2017-01-02 2017-11-12 Something
345 55 2017-01-02 9999-12-31 Something

在上表中,我需要删除第 2 行和第 6 行,因为 VisitationsId 与上一行相同,但它们在 StopDato 上存在差异。

在查询中的任何位置使用 group by 都会在另一个(看似随机的)列上给我一个错误,告诉我该列是:

在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。

对我如何做这件事有什么建议吗?

【问题讨论】:

  • 请用一些示例数据创建一个minimal reproducible example 来说明您的意思。只需过滤掉日期为'9999-12-31'的所有行?
  • @DaleK 否,'9999-12-31' 仅在 VisitationsId 不唯一的行上才无效。我根本不应该有任何重复的 VisitationsId,而且是额外的 StopDato 造成了问题。除此之外,我已经尽了我最大的努力,一个最小的可重现示例 - 使用所有连接,显示示例数据几乎是不可能的......
  • @DaleK 添加了一个简单的表格来更好地说明 - 希望它有意义!

标签: sql sql-server tsql group-by min


【解决方案1】:

添加一个过滤器来测试这种情况?

with cte (
    {your current query}
)
select *
from cte T
where not (
    StopDato = '9999-12-31'
    and exists (
       select 1
       from cte T1
       where T1.VisitationsId = T.VisitationsId
       and StopDato != '9999-12-31'
    )
);

而且您看起来正在将 StopDato 转换为不好的 varchar - 您应该将日期视为日期,直到您需要显示它们。

【讨论】:

  • 感觉方向正确,但是因为 StopDato 是由多个自定义列组成的,所以我得到“Msg 207, Level 16, State 1, Procedure v_RCVLI_Test, Line 73 [Batch Start Line 0] Invalid column name 'StopDato'。”我的语法有什么?不是(StopDato = '9999-12-31' 并且存在(从 nexus2.Fact_VisiteretTid 中选择 1,其中 VisitationId = VisitationId))
  • 尝试使用 CTE,因为我已经更新了我的问题。
  • "您看起来好像将 StopDato 转换为一个不好的 varchar - 您应该将日期视为日期,直到您需要显示它们。" - 就像我在这里说的新的一样。有没有更好的方法将 9999-12-31 转换为当前日期?
  • 好吧,convert(varchar(10), getdate(), 23) 应该是 getdate()'9999-12-31' 可以是 convert(date, '9999-12-31')
  • 我已经验证了数据并且像上面那样做不会干扰当前日期的有效记录
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 2022-10-06
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
相关资源
最近更新 更多