具有多个条件的CASE-Teradata / SQL

时间:2018-10-18 00:26:44

标签: sql teradata teradata-sql-assistant

我的数据集在Teradata中如下所示:

╔═══════════╦══════════╦══════╗
║ studentid ║   date   ║ days ║
╠═══════════╬══════════╬══════╣
║      1000 ║ 2/1/2017 ║   25 ║
║      1000 ║ 3/8/2017 ║   30 ║
║      1000 ║ 4/4/2017 ║   80 ║
║      1000 ║ 5/1/2017 ║   81 ║
║      1001 ║ 1/1/2017 ║   60 ║
║      1001 ║ 2/1/2017 ║   20 ║
║      1001 ║ 4/1/2017 ║   81 ║
╚═══════════╩══════════╩══════╝

我想有一个新的列(标志),如果最近两个日期都为80或81,则行上应显示1。如果不为0。

对于学生1001,所有行都应为0,因为最后两个日期不是80或81。它需要使用最后两个日期。即使1001的数字为81,倒数第二个日期的数字也为20,因此两者的标记都必须为0

所需的输出:

╔═══════════╦══════════╦══════╦══════╗
║ studentid ║   date   ║ days ║ flag ║
╠═══════════╬══════════╬══════╬══════╣
║      1000 ║ 2/1/2017 ║   25 ║    0 ║
║      1000 ║ 3/8/2017 ║   30 ║    0 ║
║      1000 ║ 4/4/2017 ║   80 ║    1 ║
║      1000 ║ 5/1/2017 ║   81 ║    1 ║
║      1001 ║ 1/1/2017 ║   60 ║    0 ║
║      1001 ║ 2/1/2017 ║   20 ║    0 ║
║      1001 ║ 4/1/2017 ║   81 ║    0 ║
╚═══════════╩══════════╩══════╩══════╝

2 个答案:

答案 0 :(得分:0)

row_number分配行号,然后获取每个学生ID的最后两行的minmax值。之后,使用case表达式检查条件以分配标志。

select studentid,dt,days
,case when rnum in (1,2) and max_days_latest_2 in (80,81) and min_days_latest_2 in (80,81) then 1 else 0 end as flag
from (select t.*
      ,max(case when rnum in (1,2) then days end) over(partition by studentid) as max_days_latest_2
      ,min(case when rnum in (1,2) then days end) over(partition by studentid) as min_days_latest_2
      from (select t.*,row_number() over(partition by studentid order by dt desc) as rnum
            from tbl t
           ) t
     ) t

答案 1 :(得分:0)

对于前两行,您可以应用简单的逻辑,这将在Explain中产生一个 STAT步骤

如果当前行是第一行:请检查此行和下一行是否都包含这些值之一

如果当前行是第二行:请检查此行和上一行是否都包含这些值之一

Segmentation fault Exited with code 139

如果您的Teradata版本不支持SELECT studentid, date_, Days, CASE Row_Number() Over (PARTITION BY studentid ORDER BY date DESC) WHEN 1 THEN CASE WHEN Days IN (80,81) -- AND Min(Days) Over (PARTITION BY studentid ORDER BY date DESC ROWS BETWEEN 1 Following AND 1 Following) IN (80,81) AND Lead(Days) Over (PARTITION BY studentid ORDER BY date DESC) IN (80,81) THEN 1 ELSE 0 END WHEN 2 THEN CASE WHEN Days IN (80,81) -- AND Min(Days) Over (PARTITION BY studentid ORDER BY date DESC ROWS BETWEEN 1 Preceding AND 1 Preceding) IN (80,81) AND Lag(Days) Over (PARTITION BY studentid ORDER BY date DESC) IN (80,81) THEN 1 ELSE 0 END ELSE 0 END AS flag FROM tab / lead,请使用lag语法。

但是,如果您需要将此逻辑应用于> 2行,则需要一种更通用的方法:

min