【问题标题】:how to add a filter on the partition by如何在分区上添加过滤器
【发布时间】:2019-09-13 09:46:59
【问题描述】:

我正在使用 sql oracle。

我有一张带有 emplid 和 effdt 的表格。我想在我的选择中添加一个给出 current_flag 的列。我认为这个查询会做:

select emplid,effdt,
    CASE ROW_NUMBER() OVER(PARTITION BY emplid order by effdt desc) 
        WHEN 1 THEN 'Y'
        ELSE 'N' 
    END CURRENT_FLAG
from job_table

问题是我想要一个 'Y' 表示 最高 effdt 的 emplid,但 effdt 。

例子:

emplid  effdt
x   01/01/2014
x   01/01/2015
x   01/01/2016
y   01/01/2014
y   01/01/2015
y   01/01/2016
y   01/01/2020

我的查询是“Y”

适用于 2014 年 1 月 1 日的 X 和
2020 年 1 月 1 日为 y。

但我想要结果:

emplid  effdt   current_flag
x   01/01/2014  N
x   01/01/2015  N
x   01/01/2016  Y
y   01/01/2014  N
y   01/01/2015  N
y   01/01/2016  Y
y   01/01/2020  N

因为 01/01/2020 不是当前的,而是未来的。 或者可能是 2020 年 1 月 1 日日期 Y 的“F”,以表明它在未来。

我想在我的分区上放置一个过滤器effdt < sysdate,但我不知道怎么做。

【问题讨论】:

  • 你不能试试WHEN 1 and effdt < sysdate THEN 'Y'

标签: sql oracle window-functions


【解决方案1】:

请试试这个。它必须工作

如果我理解任务

   with tbl  as 
    (SELECT 'x' as id, to_date('01/01/2014', 'dd/mm/yyyy') as dt FROM dual
    UNION ALL
    SELECT 'x' as id, to_date('01/01/2015', 'dd/mm/yyyy') as dt FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2015', 'dd/mm/yyyy') FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2016', 'dd/mm/yyyy') FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2020', 'dd/mm/yyyy') FROM dual)
    select id, dt, 
        CASE ROW_NUMBER() OVER(PARTITION BY id order by case when dt > sysdate then to_date('01/01/1970', 'dd/mm/yyyy') else dt end  desc) 
            WHEN 1 THEN 'Y'
            ELSE 'N' 
        END flg
    from tbl

如果我理解任务,您可以在“案例”中使用“F”标记日期: 当 effdt

    with tbl  as 
    (SELECT 'x' as id, to_date('01/01/2014', 'dd/mm/yyyy') as dt FROM dual
    UNION ALL
    SELECT 'x' as id, to_date('01/01/2015', 'dd/mm/yyyy') as dt FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2015', 'dd/mm/yyyy') FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2016', 'dd/mm/yyyy') FROM dual
    UNION ALL
    SELECT 'y' as id, to_date('01/01/2020', 'dd/mm/yyyy') FROM dual)
    select id, dt, 
        CASE WHEN dt > sysdate  THEN 'F'
            WHEN ROW_NUMBER() OVER (PARTITION BY id order by case when dt > sysdate 
                then to_date('01/01/1970', 'dd/mm/yyyy') else dt end  desc) = 1 
            THEN 'Y'
            ELSE 'N' 
        END flg
    from tbl

x   01.01.2015  Y
x   01.01.2014  N
y   01.01.2016  Y
y   01.01.2015  N
y   01.01.2020  F

【讨论】:

  • @BigJo。 . .如果员工只有未来的日期,这将不起作用。
  • 是的,你是对的。是的,你是对的,但是顺序可以改变: CASE WHEN dt > sysdate THEN 'F' WHEN ROW_NUMBER() OVER (PARTITION BY id order by case when dt > sysdate then to_date('01/01/1970', 'dd/ mm/yyyy') else dt end desc) = 1 THEN 'Y' ELSE 'N' END flg
【解决方案2】:

我会推荐:

select jt.*,
       (case when max(case when effdt < sysdate then effdt end) over (partition by empid) = effdt
             then 'Y' else 'N'
        end)
from job_table jt;

Here 是一个 dbfiddle,说明这在 Rustam 的答案不起作用的地方有效。

这假定日期是唯一的。

如果可以的话,可以使用row_number(),不过有点麻烦:

select jt.*,
       (case when row_number() over (partition by empid
                                     order by case when effdt < sysdate then 1 else 2 end, effdt desc
                                    ) and
                  effdt < sysdate
             then 'Y' else 'N'
        end)
from job_table jt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 2014-09-11
    • 1970-01-01
    • 2017-02-08
    相关资源
    最近更新 更多