SQL: 如何找到从一列到下一列最接近匹配的索引日期?
SQL: How to find the indexed date of the closest match from one column to the next?
我有以下示例 MyTable,它是根据原始数据集分组的。
我想找到“plus_one”值与给定“部门”中的“值”列最接近的匹配项(上面的第一个结果)的日期。这需要在“return_dt”栏中制作。
例如,在第一行中,“服装”部门的“plus_one”列中的 1.2 最接近“价值”列中的 1.36667,因此第一行需要 return 同一部门的“return_dt”列中的相应日期 (6/19/20)。
我熟悉 window 函数并使用 ORDER BY abs() 找到最接近的匹配项。我无法将它们放在一起以在单个 table.
中找到索引日期
end_dt
dept
value
plus_one
return_dt
6/30/2020 0:00
Clothes
0.2
1.2
6/19/2020
6/29/2020 0:00
Clothes
0.393333
1.393333
6/18/2020
6/28/2020 0:00
Clothes
0.393333
1.393333
6/18/2020
6/27/2020 0:00
Clothes
0.393333
1.393333
6/17/2020
6/26/2020 0:00
Clothes
0.573333
1.573333
6/17/2020
6/25/2020 0:00
Clothes
0.726667
1.726667
6/16/2020
6/24/2020 0:00
Clothes
0.853333
1.853333
6/15/2020
6/23/2020 0:00
Clothes
1.02
2.02
6/12/2020
6/22/2020 0:00
Clothes
1.166667
2.166667
6/12/2020
6/21/2020 0:00
Clothes
1.166667
2.166667
6/20/2020 0:00
Clothes
1.166667
2.166667
6/19/2020 0:00
Clothes
1.366667
2.366667
6/18/2020 0:00
Clothes
1.5
2.5
6/17/2020 0:00
Clothes
1.713333
2.713333
6/16/2020 0:00
Clothes
1.84
2.84
6/15/2020 0:00
Clothes
1.986667
2.986667
6/14/2020 0:00
Clothes
1.986667
2.986667
6/13/2020 0:00
Clothes
1.986667
2.986667
6/12/2020 0:00
Clothes
2.24
3.24
…
…
…
…
…
6/30/2020 0:00
Toys
0.2
1.2
6/19/2020
6/29/2020 0:00
Toys
0.393333
1.393333
6/18/2020
6/28/2020 0:00
Toys
0.393333
1.393333
6/18/2020
6/27/2020 0:00
Toys
0.393333
1.393333
6/17/2020
6/26/2020 0:00
Toys
0.573333
1.573333
6/17/2020
6/25/2020 0:00
Toys
0.726667
1.726667
6/16/2020
6/24/2020 0:00
Toys
0.853333
1.853333
6/15/2020
6/23/2020 0:00
Toys
1.02
2.02
6/12/2020
6/22/2020 0:00
Toys
1.166667
2.166667
6/12/2020
6/21/2020 0:00
Toys
1.166667
2.166667
6/20/2020 0:00
Toys
1.166667
2.166667
6/19/2020 0:00
Toys
1.366667
2.366667
6/18/2020 0:00
Toys
1.5
2.5
6/17/2020 0:00
Toys
1.713333
2.713333
6/16/2020 0:00
Toys
1.84
2.84
6/15/2020 0:00
Toys
1.986667
2.986667
6/14/2020 0:00
Toys
1.986667
2.986667
6/13/2020 0:00
Toys
1.986667
2.986667
6/12/2020 0:00
Toys
2.24
3.24
…
…
…
…
…
6/30/2020 0:00
Games
0.2
1.2
6/19/2020
6/29/2020 0:00
Games
0.393333
1.393333
6/18/2020
6/28/2020 0:00
Games
0.393333
1.393333
6/18/2020
6/27/2020 0:00
Games
0.393333
1.393333
6/17/2020
6/26/2020 0:00
Games
0.573333
1.573333
6/17/2020
6/25/2020 0:00
Games
0.726667
1.726667
6/16/2020
6/24/2020 0:00
Games
0.853333
1.853333
6/15/2020
6/23/2020 0:00
Games
1.02
2.02
6/12/2020
6/22/2020 0:00
Games
1.166667
2.166667
6/12/2020
6/21/2020 0:00
Games
1.166667
2.166667
6/20/2020 0:00
Games
1.166667
2.166667
6/19/2020 0:00
Games
1.366667
2.366667
6/18/2020 0:00
Games
1.5
2.5
6/17/2020 0:00
Games
1.713333
2.713333
6/16/2020 0:00
Games
1.84
2.84
6/15/2020 0:00
Games
1.986667
2.986667
6/14/2020 0:00
Games
1.986667
2.986667
6/13/2020 0:00
Games
1.986667
2.986667
6/12/2020 0:00
Games
2.24
3.24
…
…
…
…
…
我试过类似
的相关查询
select t.*,
(select t2.end_dt
from t t2
where t2.value > t.plus_one
order by t2.value
limit 1
) as return_dt
from t;
但 Netezza 显示“错误 [HY000] 错误:(2) 不支持这种形式的相关查询 - 考虑重写”
关于如何为 return_dt 创建列的任何想法?
横向连接或相关子查询似乎是这种最简单的方法:
select t.*,
(select t2.end_dt
from t t2
where t2.dept = t.dept and
t2.value > t.plus_one
order by t2.value
limit 1
) as return_dt
from t;
在没有相关子查询的情况下编写起来相当痛苦(而且效率低下)。但 。 . .
select t.*
from (select t.end_dt, t.dept, t.value, t.plus_one,
tnext.end_dt as return_dt,
row_number() over (partition by t.end_dt, t.dept, t.value, t.plus_one order by tnext.value asc) as seqnum
from t left join
t tnext
on tnext.dept = t.dept and
tnext.value > t.plus_one
) t
where seqnum = 1;
我有以下示例 MyTable,它是根据原始数据集分组的。
我想找到“plus_one”值与给定“部门”中的“值”列最接近的匹配项(上面的第一个结果)的日期。这需要在“return_dt”栏中制作。
例如,在第一行中,“服装”部门的“plus_one”列中的 1.2 最接近“价值”列中的 1.36667,因此第一行需要 return 同一部门的“return_dt”列中的相应日期 (6/19/20)。
我熟悉 window 函数并使用 ORDER BY abs() 找到最接近的匹配项。我无法将它们放在一起以在单个 table.
中找到索引日期end_dt | dept | value | plus_one | return_dt |
---|---|---|---|---|
6/30/2020 0:00 | Clothes | 0.2 | 1.2 | 6/19/2020 |
6/29/2020 0:00 | Clothes | 0.393333 | 1.393333 | 6/18/2020 |
6/28/2020 0:00 | Clothes | 0.393333 | 1.393333 | 6/18/2020 |
6/27/2020 0:00 | Clothes | 0.393333 | 1.393333 | 6/17/2020 |
6/26/2020 0:00 | Clothes | 0.573333 | 1.573333 | 6/17/2020 |
6/25/2020 0:00 | Clothes | 0.726667 | 1.726667 | 6/16/2020 |
6/24/2020 0:00 | Clothes | 0.853333 | 1.853333 | 6/15/2020 |
6/23/2020 0:00 | Clothes | 1.02 | 2.02 | 6/12/2020 |
6/22/2020 0:00 | Clothes | 1.166667 | 2.166667 | 6/12/2020 |
6/21/2020 0:00 | Clothes | 1.166667 | 2.166667 | |
6/20/2020 0:00 | Clothes | 1.166667 | 2.166667 | |
6/19/2020 0:00 | Clothes | 1.366667 | 2.366667 | |
6/18/2020 0:00 | Clothes | 1.5 | 2.5 | |
6/17/2020 0:00 | Clothes | 1.713333 | 2.713333 | |
6/16/2020 0:00 | Clothes | 1.84 | 2.84 | |
6/15/2020 0:00 | Clothes | 1.986667 | 2.986667 | |
6/14/2020 0:00 | Clothes | 1.986667 | 2.986667 | |
6/13/2020 0:00 | Clothes | 1.986667 | 2.986667 | |
6/12/2020 0:00 | Clothes | 2.24 | 3.24 | |
… | … | … | … | … |
6/30/2020 0:00 | Toys | 0.2 | 1.2 | 6/19/2020 |
6/29/2020 0:00 | Toys | 0.393333 | 1.393333 | 6/18/2020 |
6/28/2020 0:00 | Toys | 0.393333 | 1.393333 | 6/18/2020 |
6/27/2020 0:00 | Toys | 0.393333 | 1.393333 | 6/17/2020 |
6/26/2020 0:00 | Toys | 0.573333 | 1.573333 | 6/17/2020 |
6/25/2020 0:00 | Toys | 0.726667 | 1.726667 | 6/16/2020 |
6/24/2020 0:00 | Toys | 0.853333 | 1.853333 | 6/15/2020 |
6/23/2020 0:00 | Toys | 1.02 | 2.02 | 6/12/2020 |
6/22/2020 0:00 | Toys | 1.166667 | 2.166667 | 6/12/2020 |
6/21/2020 0:00 | Toys | 1.166667 | 2.166667 | |
6/20/2020 0:00 | Toys | 1.166667 | 2.166667 | |
6/19/2020 0:00 | Toys | 1.366667 | 2.366667 | |
6/18/2020 0:00 | Toys | 1.5 | 2.5 | |
6/17/2020 0:00 | Toys | 1.713333 | 2.713333 | |
6/16/2020 0:00 | Toys | 1.84 | 2.84 | |
6/15/2020 0:00 | Toys | 1.986667 | 2.986667 | |
6/14/2020 0:00 | Toys | 1.986667 | 2.986667 | |
6/13/2020 0:00 | Toys | 1.986667 | 2.986667 | |
6/12/2020 0:00 | Toys | 2.24 | 3.24 | |
… | … | … | … | … |
6/30/2020 0:00 | Games | 0.2 | 1.2 | 6/19/2020 |
6/29/2020 0:00 | Games | 0.393333 | 1.393333 | 6/18/2020 |
6/28/2020 0:00 | Games | 0.393333 | 1.393333 | 6/18/2020 |
6/27/2020 0:00 | Games | 0.393333 | 1.393333 | 6/17/2020 |
6/26/2020 0:00 | Games | 0.573333 | 1.573333 | 6/17/2020 |
6/25/2020 0:00 | Games | 0.726667 | 1.726667 | 6/16/2020 |
6/24/2020 0:00 | Games | 0.853333 | 1.853333 | 6/15/2020 |
6/23/2020 0:00 | Games | 1.02 | 2.02 | 6/12/2020 |
6/22/2020 0:00 | Games | 1.166667 | 2.166667 | 6/12/2020 |
6/21/2020 0:00 | Games | 1.166667 | 2.166667 | |
6/20/2020 0:00 | Games | 1.166667 | 2.166667 | |
6/19/2020 0:00 | Games | 1.366667 | 2.366667 | |
6/18/2020 0:00 | Games | 1.5 | 2.5 | |
6/17/2020 0:00 | Games | 1.713333 | 2.713333 | |
6/16/2020 0:00 | Games | 1.84 | 2.84 | |
6/15/2020 0:00 | Games | 1.986667 | 2.986667 | |
6/14/2020 0:00 | Games | 1.986667 | 2.986667 | |
6/13/2020 0:00 | Games | 1.986667 | 2.986667 | |
6/12/2020 0:00 | Games | 2.24 | 3.24 | |
… | … | … | … | … |
我试过类似
的相关查询select t.*,
(select t2.end_dt
from t t2
where t2.value > t.plus_one
order by t2.value
limit 1
) as return_dt
from t;
但 Netezza 显示“错误 [HY000] 错误:(2) 不支持这种形式的相关查询 - 考虑重写”
关于如何为 return_dt 创建列的任何想法?
横向连接或相关子查询似乎是这种最简单的方法:
select t.*,
(select t2.end_dt
from t t2
where t2.dept = t.dept and
t2.value > t.plus_one
order by t2.value
limit 1
) as return_dt
from t;
在没有相关子查询的情况下编写起来相当痛苦(而且效率低下)。但 。 . .
select t.*
from (select t.end_dt, t.dept, t.value, t.plus_one,
tnext.end_dt as return_dt,
row_number() over (partition by t.end_dt, t.dept, t.value, t.plus_one order by tnext.value asc) as seqnum
from t left join
t tnext
on tnext.dept = t.dept and
tnext.value > t.plus_one
) t
where seqnum = 1;