我是SQL新手,我试图在网上搜索类似的帖子,但一无所获。那就这样吧
我有一个表t1
,它用以下列整理调查响应:date
、id
、group
和level
。还有更多的列,但这些基本上是我关心的。前3列告诉我谁回答了调查以及何时回答(id
和group
列值之间存在多对多关系)。每个id
-group
组合在每个月最多有1个条目(日期值与该月的第一天挂钩)。level
列是他们对调查的回应。
对于现有的每对id
和group
,我想获得2022年和2023年每个月的level
。问题是,我在那一栏里有很多空白。举个小例子:
日期|id|群|水准仪
2022-01-01 2022-01-01| 1|一个|零
2022-02-01 2022 -02-01| 1|一个|3
2022-03-01 2022-03-01| 1|一个|零
2022-04-01 2022-04-01| 1|一个|零
2022-05-01 2022-05-01| 1|一个|4
2022-06-01 2022-06-01| 1|一个|5个
2022-07-01 2022-07-01| 1|一个|零
所以,我想推断一下我现有的数据。对于level
为空的每一行,我希望分配在“缺失”月份之前的最近非空月份的level
。如果具有空值的行没有具有非空值的前一个月(即它是2022年1月),获取最早月份的值,其中非空level
出现在空行之后。因此,期望的输出将是:
日期|id|群|水准仪
2022-01-01 2022-01-01| 1|一个|3
2022-02-01 2022 -02-01| 1|一个|3
2022-03-01 2022-03-01| 1|一个|3
2022-04-01 2022-04-01| 1|一个|3
2022-05-01 2022-05-01| 1|一个|4
2022-06-01 2022-06-01| 1|一个|5个
2022-07-01 2022-07-01| 1|一个|5个
我的方法是这样的:我使用了一个表t2
来获取t1
中具有非空level
值的所有行。然后,我创建了CTE t3
,基本上是t1
的副本,多了一个名为insert
的列。这个新列将是我放置外推的t1.level
值的地方,我将使用一个简单的更新函数将t3.insert
传输到相应的空t1.level
行。
with t3 as
Select distinct t1.date, t1.id, t1.group, t1.level,
Case
--for when the null t1 record is earlier than the earliest t2 record
When (t2.date = (select min(t2.date) where (t1.id, t1.group) = (t2.id, t2.group)))
Then t2.level
--when the null t1 record is later than some existing t2 record
When (t2.date = (select max(t2.date) where (t1.id, t1.group) = (t2.id, t2.group) AND t2.date <= t1.date))
Then t2.level
Else null
End as "insert"
from t1
Join t2 on (t1.id, t1.group) = (t2.id, t2.group)
GROUP BY t1.date, t1.id, t1.group, t1.level, t2.id, t2.group, t2.date, t2.level
ORDER BY t1.id, t1.group, t1.date
)
我甚至无法进入更新t1.level
的部分,因为我遇到了问题。我发现对于每一对id
和group
,t3
将每个t2.level
值分配给每个t3.insert
。对于2022年1月id
= 1和group
= A的记录:
日期|id|群|水准仪|插入
2022-01-01 2022-01-01| 1|一个|零|3
2022-01-01 2022-01-01| 1|一个|零|4
2022-01-01 2022-01-01| 1|一个|零|5个
似乎postgresql忽略了case语句中的min()函数。我可能犯了一个很低级的错误。
1条答案
按热度按时间oxcyiej71#
下面的查询演示了一种确定NULL调查级别的替代值的方法,方法是查找前一个非NULL级别,如果不存在,则查找下一个非NULL级别。
前一个值和下一个值被收集到数组中,数组的第一个元素是给定方向上最近的非NULL值。因为先前的值是按降序排序的,所以使用
FOLLOWING
而不是PRECEDING
来定义窗口框架。