我正在使用 Netezza SQL。
我有下表:
CREATE TABLE sample_table
(
name VARCHAR(50),
year INTEGER,
color VARCHAR(50)
);
INSERT INTO sample_table (name, year, color)
VALUES ('aaa', 2010, 'Red');
INSERT INTO sample_table (name, year, color)
VALUES ('aaa', 2012, 'Red');
INSERT INTO sample_table (name, year, color)
VALUES ('bbb', 2014, 'Blue');
INSERT INTO sample_table (name, year, color)
VALUES ('bbb', 2016, 'Blue');
桌子看起来像这样:
+------+--------+-------+
| name | year | color |
+------+--------+-------+
| aaa | 2010 | Red |
| aaa | 2012 | Red |
| bbb | 2014 | Blue |
| bbb | 2016 | Blue |
+------+--------+-------+
如我们所见:
我的问题: 我想编写一个 SQL 查询,为这两个名称添加这些缺失的行(假设每个“名称”的“颜色”保持不变)。最终输出应该是这个样子:
+------+--------+-------+
| name | year | color |
+------+--------+-------+
| aaa | 2010 | Red |
| aaa | 2011 | Red |
| aaa | 2012 | Red |
| bbb | 2014 | Blue |
| bbb | 2015 | Blue |
| bbb | 2016 | Blue |
+------+--------+-------+
在上一个问题中,我学习了如何使用递归 CTE 解决类似问题(Adding Missing Rows in SQL using JOINS)。有人可以告诉我如何通过创建中间表来尝试解决这个问题吗? (例如 temp_tab1, temp_tab2, ... drop temp_tab1)
我仍在学习 SQL,发现更容易理解更小的代码块
谢谢!
为了避免递归,你可以有一个表列出所有可能的年份,你会用它来生成每个产品的“缺失”行,比如
years_table(years)
。
我们通常会在子查询中生成每个名称的开始和结束年份,然后从年份表中提取所有年份,最后检查我们是否在原始数据中有匹配项,使用
left join
;
select n.name, y.year, t.color
from (
select name, min(year) min_year, max(year) max_year
from sample_table
group by name
) n
inner join years_table y on y.year between n.min_year and n.max_year
left join sample_table t on t.name = n.name and t.year = y.year
这有效,但不会为查询逻辑“添加”的行提供颜色。为此,我们需要做更多的工作(这是一个差距和孤岛问题)。这是一种方法:
select name, year, max(color) over(partition by name, grp order by year) color
from (
select n.name, y.year, t.color,
sum(case when t.name is null then 0 else 1 end) over(partition by n.name order by y.year) grp
from (
select name, min(year) min_year, max(year) max_year
from sample_table
group by name
) n
inner join years_table y on y.year between n.min_year and n.max_year
left join sample_table t on t.name = n.name and t.year = y.year
) t
这也是我在这里提倡递归查询的另一个原因。这个想法是识别日期系列中的间隙,并使用递归仅生成缺失的行。由于递归查询从锚点开始,因此很容易跟踪“当前”颜色。
with recursive
data as (
select t.*, lead(year) over(partition by name order by year) lead_year
from sample_table t
),
rec as (
select name, year, color, lead_year from data where lead_year > year + 1
union all
select name, year + 1, color, lead_year from rec where lead_year > year + 1
)
select name, year, color from data where lead_year is null or lead_year = year + 1
union all
select name, year, color from rec
order by name, year
这里:
data
查找“下一个”可用年份,这可以识别差距rec
从每个空隙开始,生成新的行,直到到达下一个岛,跟踪原始颜色union
将原始岛屿和我们填补的空白结合在一起这是 DB Fiddle 上的demo,其中有几行添加到您的数据中,并且两种解决方案都在工作。
输入:
姓名 | 年 | 颜色 |
---|---|---|
aaa | 2010 | 红色 |
aaa | 2012 | 红色 |
aaa | 2013 | 蓝色 |
aaa | 2016 | 蓝色 |
bb | 2014 | 蓝色 |
bb | 2016 | 蓝色 |
输出:
姓名 | 年 | 颜色 |
---|---|---|
aaa | 2010 | 红色 |
aaa | 2011 | 红色 |
aaa | 2012 | 红色 |
aaa | 2013 | 蓝色 |
aaa | 2014 | 蓝色 |
aaa | 2015 | 蓝色 |
aaa | 2016 | 蓝色 |
bb | 2014 | 蓝色 |
bb | 2015 | 蓝色 |
bb | 2016 | 蓝色 |