在考虑地区的同时将门牌号聚合到 MIN 和 MAX
Aggregate house numbers to MIN and MAX while considering districts
我想获得 MIN / MAX 门牌号,这很容易。
但是有一个包含区的列。
原始数据:
Street Name | House Number | district
Hauptstr. | 1 | A
Hauptstr. | 2 | A
Hauptstr. | 3 | B
Hauptstr. | 4 | B
Hauptstr. | 5 | A
期望输出:
Street Name | House number (FROM) | House number (TO) | district
Hauptstr. | 1 | 2 | A
Hauptstr. | 3 | 4 | B
Hauptstr. | 5 | 5 | A
我的输出:
Street Name | House number (FROM) | House number (TO) | district
Hauptstr. | 1 | 5 | A
Hauptstr. | 3 | 4 | B
我乐于接受想法和建议。我需要临时 table 来处理地址吗?
提前致谢。
假设您正在开发支持它们的 SQL 实现,您可以在(未测试)[=14= 行中使用 FIRST_VALUE
和 LAST_VALUE
等分析函数]
select streetname
,first_value(housenumber) over (order by streetname, housenumber partition by district) as from
,last_value(housenumber) over (order by streetname, housenumber partition by district) as to
,district
from table
编辑:该查询不起作用,但应该可以。
EDIT2:这是一种(有点复杂的)方法
select *
from (
select streetname
,district
,from_num
,coalesce(to_num,lead(to_num,1) over (partition by streetname order by housenumber)) as to_num
from (
select streetname
,housenumber
,district
,case when coalesce(lag(district,1) over (partition by streetname order by housenumber),'') <> district then housenumber end as from_num
,case when coalesce(lead(district,1) over (partition by streetname order by housenumber),'') <> district then housenumber end as to_num
from table
)
where from_num is not null or to_num is not null
)
where from_num is not null
这是在 DB2 中测试的。我不知道 MaxDB,因此您可能需要调整语法。
至于发生了什么的解释:
- 在第一遍(最内层的子查询)中,我首先查看(即,当上一个地区与当前地区不同时)和最后(即,当下一个地区与当前地区不同时)每个记录按街道名称和门牌号排序的地区组。如果是第一个,那么我将门牌号存储为'from';如果最后,我将其存储为 'to'
- 从那以后,我 select 只有每个组的第一个和最后一个记录(即那些 'from' 或 'to' 值被填充的记录。这让我每组 1 到最多 2 条记录。对于没有填写 'to' 值的每条记录,我用下一条记录中的值填写它。
- 剩下要做的就是 select 从这个子结果中只得到那些同时填写了两个值的记录,瞧!
您可以在 MySQL 中使用变量执行此操作。它为相邻街道值的每一行分配一个组:
select street, district, min(housenumber), max(housenumber)
from (select t.*,
(@grp := if(@d = district, @grp,
if(@d := district, @grp + 1, @grp + 1)
)
) as grp
from t cross join
(select @d := '', @grp := 0) params
order by street, housenumber
) t
group by grp, street, district;
我想获得 MIN / MAX 门牌号,这很容易。
但是有一个包含区的列。
原始数据:
Street Name | House Number | district
Hauptstr. | 1 | A
Hauptstr. | 2 | A
Hauptstr. | 3 | B
Hauptstr. | 4 | B
Hauptstr. | 5 | A
期望输出:
Street Name | House number (FROM) | House number (TO) | district
Hauptstr. | 1 | 2 | A
Hauptstr. | 3 | 4 | B
Hauptstr. | 5 | 5 | A
我的输出:
Street Name | House number (FROM) | House number (TO) | district
Hauptstr. | 1 | 5 | A
Hauptstr. | 3 | 4 | B
我乐于接受想法和建议。我需要临时 table 来处理地址吗?
提前致谢。
假设您正在开发支持它们的 SQL 实现,您可以在(未测试)[=14= 行中使用 FIRST_VALUE
和 LAST_VALUE
等分析函数]
select streetname
,first_value(housenumber) over (order by streetname, housenumber partition by district) as from
,last_value(housenumber) over (order by streetname, housenumber partition by district) as to
,district
from table
编辑:该查询不起作用,但应该可以。
EDIT2:这是一种(有点复杂的)方法
select *
from (
select streetname
,district
,from_num
,coalesce(to_num,lead(to_num,1) over (partition by streetname order by housenumber)) as to_num
from (
select streetname
,housenumber
,district
,case when coalesce(lag(district,1) over (partition by streetname order by housenumber),'') <> district then housenumber end as from_num
,case when coalesce(lead(district,1) over (partition by streetname order by housenumber),'') <> district then housenumber end as to_num
from table
)
where from_num is not null or to_num is not null
)
where from_num is not null
这是在 DB2 中测试的。我不知道 MaxDB,因此您可能需要调整语法。 至于发生了什么的解释:
- 在第一遍(最内层的子查询)中,我首先查看(即,当上一个地区与当前地区不同时)和最后(即,当下一个地区与当前地区不同时)每个记录按街道名称和门牌号排序的地区组。如果是第一个,那么我将门牌号存储为'from';如果最后,我将其存储为 'to'
- 从那以后,我 select 只有每个组的第一个和最后一个记录(即那些 'from' 或 'to' 值被填充的记录。这让我每组 1 到最多 2 条记录。对于没有填写 'to' 值的每条记录,我用下一条记录中的值填写它。
- 剩下要做的就是 select 从这个子结果中只得到那些同时填写了两个值的记录,瞧!
您可以在 MySQL 中使用变量执行此操作。它为相邻街道值的每一行分配一个组:
select street, district, min(housenumber), max(housenumber)
from (select t.*,
(@grp := if(@d = district, @grp,
if(@d := district, @grp + 1, @grp + 1)
)
) as grp
from t cross join
(select @d := '', @grp := 0) params
order by street, housenumber
) t
group by grp, street, district;