如何仅为以前记录中未选择为 MIN 的值选择 MIN?

Posted

技术标签:

【中文标题】如何仅为以前记录中未选择为 MIN 的值选择 MIN?【英文标题】:How to select MIN only for values that have not been selected as MIN for previous records? 【发布时间】:2021-12-31 16:29:44 【问题描述】:

我正在尝试为每张尚未被选为以前发票的最低文档等级的发票选择最低文档等级。为此,我认为我需要知道所有 invoicerank

这是 2 个客户端的数据集示例:

clientid    invoicerank documentrank    documentdate
    1           1           1           04/10/2021
    1           1           2           03/03/2021
    1           1           3           02/01/2021
    1           2           1           04/10/2021
    1           2           2           03/03/2021
    1           2           3           02/01/2021
    1           3           1           04/10/2021
    1           3           2           03/03/2021
    1           3           3           02/01/2021
    2           1           null        null
    2           2           1           06/22/2021
    2           2           2           05/04/2021
    2           3           1           06/22/2021
    2           3           2           05/04/2021

这就是我希望结果的样子:

clientid    invoicerank documentrank    documentdate
    1           1           1           04/10/2021
    1           2           2           03/03/2021
    1           3           3           02/01/2021
    2           1           null        null
    2           2           1           06/22/2021
    2           3           2           05/04/2021

编辑:对于此数据集,每个现有文档都有一行可以应用于每张发票。在另一个表中选择了 documentrank,它是 dense_rank() OVER(PARTITION BY clientid ORDER BY documentdate DESC)。如果 documentrank 为空,则意味着没有可应用于该发票的现有文档。因此,对于每张发票,我想要尚未被选为任何先前发票等级的最低文档等级的最低文档等级。因此,对于 clientid=1 和 invoicerank = 2,我想选择未选择为 invoicerank=1 的最低文档等级的最低文档等级。所以 invoicerank=1 选择 1 作为最小值。 Invoicerank=2 也会选择 documentrank=1 作为最小值,但由于已经为 invoicerank=1 选择了它,我希望它选择 documentrank=2。

Edit2:我正在使用 Zoho Analytics 进行此查询。这限制了我只能使用 select 语句,并且只有 1 级嵌套子查询。窗口函数内部也不支持 case-whens。也不支持相关的子查询。

【问题讨论】:

解释你的例子。为什么是那些行?还有你用的是哪个数据库? @drum 我编辑了! 【参考方案1】:

显然,null 会影响编号。你只需要记住。

with data as (
    select *,
        rank() over (
            partition by clientid
            order by case when documentrank is null then 0 else documentrank
        ) as documentrank2
    from T
)
select * from data where invoicerank = documentrank2

我假设任何地方都不会有联系。以下应该是等价的。

select *
from (
    select *,
      (
        select count(distinct coalesce(t2.documentrank, 0)) + 1
        from T t2
        where coalesce(t2.documentrank, 0) < coalesce(T.documentrank, 0)
            and t2.clientid = T.clientid
      ) as documentrank2            
    from T
) data
where invoicerank = documentrank2

select *
from T
where invoicerank = (
    select count(distinct coalesce(t2.documentrank, 0)) + 1
    from T t2
    where coalesce(t2.documentrank, 0) < coalesce(T.documentrank, 0)
        and t2.clientid = T.clientid
)

select * from T inner join (
    select clientid,
        count(case when documentrank is null then 1 end) as ofs
    from T
    group by clientid
) t2 on t2.clientid = T.clientid
where T.invoicerank = coalesce(T.documentrank, 0) + t2.ofs

select * from T left outer join (
    select clientid, count(*) as ofs from T
    where documentrank is null
    group by clientid
) t2 on t2.clientid = T.clientid
where T.invoicerank = coalesce(T.documentrank, 0) + coalesce(t2.ofs, 0)

https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=628e84b8ad3e66b88039ae7c3f3d855c

【讨论】:

有没有办法把它写成子查询或使用自连接?我正在使用 Zoho Analytics,它只允许选择语句。 Zoho 也不支持相关子查询。由于 t2 的 where 语句使用来自外部查询的列,因此这种格式不起作用。 最后一个选项不起作用吗?

以上是关于如何仅为以前记录中未选择为 MIN 的值选择 MIN?的主要内容,如果未能解决你的问题,请参考以下文章

仅为每组记录选择最近的记录

从查询到子查询的组中未选择的值

从自动完成下拉列表中未选择任何选项时如何清除 mat- 自动完成

如何获取select2的值:取消选择

读取在 DataGridView 表中选择的记录,并将该记录的信息读取到表中未显示的字段中

选择排序