简体   繁体   English

SQL 基于有效性分组

[英]SQL Grouping based on validity

I have the following table, let's call it tbl_costcenters, with the following dummy entries:我有下表,我们称之为 tbl_costcenters,其中包含以下虚拟条目:

ID PosName CostcenterCode ValidFrom ValidUntil
1  test1   111            1.1.2019  1.6.2019
2  test1   111            1.6.2019  1.9.2019
3  test1   222            1.9.2019  1.6.2020

and i would have the following result:我会得到以下结果:

PosName  ValidFrom    ValidUntil   CostcenterCode
test1    1.1.2019     1.9.2019     111
test1    1.9.2019     1.6.2020     222

This is very simplified.这是非常简化的。 The real table contains much more cols.真正的表包含更多的列。 I need to group them based on the costcentercode and get a validity that englobes the two first entries of my example, returning the validfrom from record ID 1 and the validuntil from record ID 2.我需要根据 costcentercode 对它们进行分组,并获得包含我的示例的前两个条目的有效性,从记录 ID 1 返回 validfrom,从记录 ID 2 返回 validuntil。

Sorry i did not really know for what to search.抱歉,我真的不知道要搜索什么。 I think that the answer is easy for somebody that is strong in SQL.我认为对于 SQL 的强者来说,答案很容易。

The answer should work for both, SQL Server and for Oracle.答案应该适用于 SQL 服务器和 Oracle。

Thank you for your help.谢谢您的帮助。

This seems simple aggregation:这似乎是简单的聚合:

select PosName, 
       min(ValidFrom) as ValidFrom, 
       (case when max(ValidUntil) > min(ValidFrom) then max(ValidUntil) end) as ValidUntil, 
       CostcenterCode
from tbl_costcenters t
group by PosName, CostcenterCode; 

I suspect that you want to group togethers records whose date overlap, while keeping those that don't overlap separated (although this is not showing in your sample data).我怀疑您想将日期重叠的记录组合在一起,同时将不重叠的记录分开(尽管这没有显示在您的示例数据中)。

If so, we could use some gaps-and-island techniques here.如果是这样,我们可以在这里使用一些间隙和岛屿技术。 One option uses window functions to build groups of adjacent records:一种选择是使用 window 函数来构建相邻记录组:

select 
    postName, 
    min(validFrom) validFrom,
    max(validUntil) validUntil
    costCenter
from (
    select
        t.*,
        sum(case when validFrom <= lagValidUntil then 0 else 1 end)
            over(partition by posName, costCenter order by validFrom) grp
    from (
        select
            t.*,
            lag(validUntil) 
                over(partition by posName, costCenter order by validFrom) lagValidUntil
        from mytable t
    ) t
) t
group by postName, costCenter, grp
order by postName, validFrom

The definitve solution for me was:对我来说,明确的解决方案是:

select posname, min(validfrom), 
case 
    when 
        max(case when validuntil is null then 1 ELSE 0 END) = 0
    then max(validuntil)
end
from tbl_costcenters pos 
group by posname, costcentercode;

Thank you all.谢谢你们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM