SQL 到 select 基于特定条件的新列
SQL to select a new column based on certain conditions
请帮我创建一个SQL根据以下条件生成column3
column3的值必须以1开头
每当 Column2 的值为 'N' 时,Column3 的值必须在上一行的 Column3 的值上加 1。
每当Column2的值为'Y'时,Column3的值必须与上一行Column3的值相同
每当 Column1 的值发生变化时,Column3 的值必须重置为 1
数据样本:
谢谢
特蕾莎
解决方案
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');
第 3 列构建
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_start
和 n_value
.
id_start
:提供排序键值,id
,其中每个 column1
变化。在您对 column3
的定义中,这实际上是您的第三个项目符号。
n_value
:我们需要知道column3
的值变化的次数。根据您的定义,这仅在 column2 = 'N'
时发生,因此此列 returns 在 column1
分区内发生这种情况的次数。
一旦我们有了这两个数据,避免这个问题的迭代就很简单了:column3
是前面所有 n_value
的最大值加一。一个例外是当 Y 紧跟在分区的开头时,在这种情况下 column3
始终为 1。(这通过合并解决。)
这是一个使用 PostgreSQL 的 SqlFiddle。 Netezza 是一个变体,因此语法仍然适用。
请帮我创建一个SQL根据以下条件生成column3
column3的值必须以1开头
每当 Column2 的值为 'N' 时,Column3 的值必须在上一行的 Column3 的值上加 1。
每当Column2的值为'Y'时,Column3的值必须与上一行Column3的值相同
每当 Column1 的值发生变化时,Column3 的值必须重置为 1
数据样本:
谢谢 特蕾莎
解决方案
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');
第 3 列构建
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_start
和 n_value
.
id_start
:提供排序键值,id
,其中每个 column1
变化。在您对 column3
的定义中,这实际上是您的第三个项目符号。
n_value
:我们需要知道column3
的值变化的次数。根据您的定义,这仅在 column2 = 'N'
时发生,因此此列 returns 在 column1
分区内发生这种情况的次数。
一旦我们有了这两个数据,避免这个问题的迭代就很简单了:column3
是前面所有 n_value
的最大值加一。一个例外是当 Y 紧跟在分区的开头时,在这种情况下 column3
始终为 1。(这通过合并解决。)
这是一个使用 PostgreSQL 的 SqlFiddle。 Netezza 是一个变体,因此语法仍然适用。