SQL Server:循环遍历每个(PARTITION BY ...)元素的过程或函数

Posted

技术标签:

【中文标题】SQL Server:循环遍历每个(PARTITION BY ...)元素的过程或函数【英文标题】:SQL Server : procedure or function to loop over each (PARTITION BY ...) element 【发布时间】:2020-09-02 12:32:46 【问题描述】:

我正在通过实际示例学习 SQL 语法。我有下表:

CREATE TABLE [dbo].[Orders_tmp_test]
(
    department_id VARCHAR(4),
    rank_pr_co INT,
    starting_date DATE, 
    end_date DATE
)
 
INSERT INTO [dbo].[Orders_tmp_test]
    SELECT '1001', 1, '2019/04/01', '2020/02/01'
    UNION ALL    
    SELECT '1001', 2, '2020/01/31', '2020/04/30'
    UNION ALL     
    SELECT '1001', 3, '2020/03/01', '2020/03/01'
    UNION ALL     
    SELECT '1001', 4, '2020/03/31', '2020/05/31'
    UNION ALL     
    SELECT '1002', 1, '2019/03/01', '2020/02/01'
    UNION ALL    
    SELECT '1002', 2, '2020/01/01', '2020/04/01'

每个部门都有几个项目。项目按“rank_pr_co”提供的顺序执行。当前项目尚未结束,但给定部门的另一个项目已经开始时,称为冲突。我想修改将解决所有冲突的项目的“starting_date”和“end_date”。项目的长度是固定的。对于“starting_date”=“end_date”的项目,我想保持原样。在这种情况下,我想解决上一个项目和下一个项目之间的冲突。

最后我想要下表:

'1001', 1, '2019/04/01', '2020/02/01'
'1001', 2, '2020/02/01', '2020/05/01'
'1001', 3, '2020/03/01', '2020/03/01'
'1001', 4, '2020/05/01', '2020/07/01'
'1002', 1, '2019/03/01', '2020/02/01'
'1002', 2, '2020/02/01', '2020/05/01'

我尝试创建标量函数并将其转换为(按...分区)元素,但它不起作用并返回错误:

消息 4113,第 16 级,状态 1,第 3 行 函数“dbo.ideal_schema”不是有效的窗口函数,不能与 OVER 子句一起使用。

有人知道如何得出决赛桌吗?

【问题讨论】:

我看不出您的示例数据如何解决冲突。 用户定义的函数不能有窗口。只有特定的聚合和分析 T-SQL 函数可以。 @GordonLinoff 感谢您的快速响应。在新表中, ('1001',2) 是在上一个项目 ('1001',1) 结束时开始的。这正在解决这些项目相互冲突的时间表。 @baraban55 。 . .但它在下一个项目之后结束。 @GordonLinoff 没错!这是主要的困难。 ('1001', 3) 是特殊的。它开始和结束相同的日期(立即完成)。这就是为什么我解决了 ('1001', 2) 和 ('1001', 4) 之间的冲突并保留 ('1001', 3) 的原因。 【参考方案1】:

如果您希望项目中没有重叠日期并且结束日期不包含在内,那么只需使用lead()

select t.*,
       lead(end_date, 1, end_date) over (partition by project_id order by start_date) as imputed_end_date
from Orders_tmp_test t;

注意:这故意使用排序列。对于在日期和指定顺序彼此无关的极端情况下该怎么做,您必须有更多解释。

注意:如果你真的想update 表,这可以很容易地合并到update 语句中。我认为没有理由为此编写用户定义的函数。您可能需要一个视图,如果您希望在查询表时获得此信息。

【讨论】:

似乎“领导”功能可能是正确的方向。但是,它并不能解决一些问题。 “starting_date”和“end_date”都应该更改。此外,如果“starting_date”="end_date",那么它根本不应该改变。

以上是关于SQL Server:循环遍历每个(PARTITION BY ...)元素的过程或函数的主要内容,如果未能解决你的问题,请参考以下文章

SQL SERVER循环遍历(普通循环和游标循环)

循环遍历sql server trigger中的数据

SQL server中遍历所有行的循环表达式怎么写

SQL Server 每 5 行循环遍历一个表

SQL Server 2008 中的 While 循环遍历日期范围,然后插入

使用 itertools.cycle() 循环遍历多个列表