SQL根据特定条件选择新列

时间:2016-06-12 07:00:16

标签: sql netezza

请帮我生成SQL以根据以下条件生成column3

  • 每当Column2的值为'N'时,Column3的值必须加1到前一行中Column3的值。

  • 每当Column2的值为'Y'时,Column3的值必须与上一行中Column3的值相同

  • 每当Column1的值发生更改时,Column3的值必须重置为1

数据样本:

Column1 Column2 Column3
   1       Y       1
   1       Y       1
   1       N       2
   1       N       3
   1       Y       3
   1       Y       3
   1       Y       3
   1       Y       3
   2       Y       1
   2       Y       1
   2       N       2

由于 特雷莎

1 个答案:

答案 0 :(得分:0)

解决方案

DDL

create table so (
  id int
  ,column1 int
  ,column2 varchar(1)
);

insert into so values
  (1, 1, 'Y')
  ,(2, 1, 'Y')
  ,(3, 1, 'N')
  ,(4, 1, 'N')
  ,(5, 1, 'Y')
  ,(6, 1, 'Y')
  ,(7, 1, 'Y')
  ,(8, 1, 'Y')
  ,(9, 2, 'Y')
  ,(10, 2, 'Y')
  ,(11, 2, 'N');

Column3 Build

with str as (
  select
    *
    ,min(id) over (partition by column1) id_start
    ,case column2
      when 'N' 
        then row_number() over (
          partition by column1 
          order by column2, id
        ) 
      else null
    end n_value
  from
    so
), cls as (
  select
    *
    ,case
      when id_start = id 
        then 1
      else 
        coalesce(max(n_value) over (
          partition by column1
          order by id
          rows between unbounded preceding and current row
        ) + 1 ,1)
    end column3
  from
    str
)
select
  id
  ,column1
  ,column2
  ,column3
from 
  cls
order by 
  id

解释

您需要一个订购密钥才能成功,如其他评论和答案所示。我在DDL中人工创建了一个,但你可以使用row_number()和不同的排序键自己构建另一个。

答案中的str CTE提供了两个非常关键的列,用于从排序中提取隐式数据:id_startn_value

id_start:提供每个id更改的排序键值column1。在您对column3的定义中,这基本上是您的第三个子弹。

n_value:我们需要知道column3的值发生变化的次数。根据您的定义,这仅在column2 = 'N'时发生,因此该列返回在column1分区内发生这种情况的次数。

一旦我们拥有这两个数据,避免迭代此问题非常简单:column3是所有先前n_value s的最大值加1。一个例外是当一个Y紧跟在一个分区的开始之后,在这种情况下column3始终为1.(这是通过合并来解决的。)

这是使用PostgreSQL的SqlFiddle。 Netezza是一种变体,因此语法仍然适用于那里。