如何编写查询来清理给定问题的表

Posted

技术标签:

【中文标题】如何编写查询来清理给定问题的表【英文标题】:How to write a query to clean up table for given problem 【发布时间】:2020-06-07 08:31:53 【问题描述】:

我有一些数据库,我需要从一个表中清理一些数据,我想相当自动地这样做。

首先是架构:这个数据库中有几个表,但我只需要专门清理一个表。

表名是CollectedProducts:

[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [date] NOT NULL,
[Time] [time](7) NOT NULL,
[BouquetId] [int] NOT NULL,
[EmployeeId] [int] NOT NULL,
[ProductionEnd] [bit] NOT NULL

我对最后一列感兴趣,ProductionEnd,它指出特定员工是否在特定日期完成了生产。

此列的逻辑约束是,在给定日期的生产结束时,必须至少有一行将此列设置为 1。所以它基本上是员工在某一天的最后一行。

一天中还可以有其他行设置为 1,表示员工有更长的休息时间。

其后不得有另一行,其值设置为 1。

现在考虑到这些限制,我想选择具有无效 ProductionEnd 值的所有行,这样这不是每个(天,员工)对的最后一行,我还想保留所有带有 @ 的行987654325@ 设置为 1,这不是最后一行,但也没有后跟 / 前面有另一行,根据我上面描述的约束,此列设置为 1。

这样的查询怎么写?

【问题讨论】:

您没有给出完整的架构,因为没有表名。另外,您尝试自己编写此查询是什么? 我正在尝试选择最后一行,但我不确定如何保留那些不在最后一行的孤 1 的“岛屿”。 @kamilwydrzycki 。 . .样本数据和期望的结果会有所帮助。 【参考方案1】:

您可以使用窗口函数来做到这一点。基本上,对于每一天,您都希望有 ProductionEnd = 1 的行,并且其他行存在于稍后的时间和 ProductionEnd = 1 并且没有行存在于稍后的时间和 ProductionEnd = 0

你可以这样表述:

select *
from (
    select
        cp.*,
        sum(ProductionEnd) 
            over(partition by EmployeeId, Date order by Time desc) nbProdEnd,
        sum(case when ProductionEnd = 1 then 0 else 1 end)
            over(partition by EmployeeId, Date order by Time desc) nbNonProdEnd
    from CollectedProducts cp
) t
where nbProdEnd > 1 and nbNonProdEnd = 0

【讨论】:

【参考方案2】:

如果您只想要最后一行不是“1”的日期/员工对,那么您可以使用first_value()。以下获取员工日期的所有行:

select cp.*
from (select cp.*,
             first_value(productionEnd) over (partition by EmployeeId, Date order by Time desc) as last_productionEnd
      from CollectedProducts cp
     ) cp
where last_productionEnd <> 1;

如果你只想要最后一个,你可以使用:

select cp.*
from (select cp.*,
             row_number() over (partition by EmployeeId, Date order by Time desc) as seqnum
      from CollectedProducts cp
     ) cp
where seqnum = 1 and last_productionEnd <> 1;

【讨论】:

以上是关于如何编写查询来清理给定问题的表的主要内容,如果未能解决你的问题,请参考以下文章

如何从给定查询编写优化查询?

如何编写子查询以动态地从未确定的表中获取相同的字段

MySQL 查询:如何在 Django 中编写?

如何编写带有联接和聚合的 SQLAlchemy 查询?

如何编写一个 JPQL 查询来查找此连接中未找到的记录?

如何根据状态编写过滤国家/地区的 sql 查询