sql - 将包含子字符串的多行折叠成一行
问题描述
我有几行记录 ( id, query,count
),我想通过观察query
多行来折叠它们。我想保留折叠行的最长行query
和字段总和。count
样本输入:
24, que, 2
24, querie, 1
24, queries, 1
25, term1, 3
25, term1+term2, 11
25, term1+term2+term3, 1
26, inventory, 5
26, issues, 10
27, close, 1
27, sclosed, 2
28, abcde, 2
28, abcfe, 2
所需输出:
24, queries, 4
25, term1+term2+term3, 15
26, inventory, 5
26, issues, 10
27, close, 1
27, sclosed, 2
28, abcde, 2
28, abcfe, 2
我只是在子字符串的特殊情况之后:24,25
被折叠但27
不是,由于前缀 on close
。26
也不会折叠,因为query
第二行中的字段不是第一行的子字符串(没有前缀)。
编辑:添加了 id 28
,这是不应该折叠记录的另一种情况。
解决方案
对于更一般的情况(例如“差异可能在第 10 个字母”或“有一行只有一个字符”),您需要确定正确的组。所以有必要对照下一行检查行:“当前行是下一行的开始吗?”
有了一些东西,substring
你可以在开头检查一个特殊的长度(“对所有以相同的 3 个字母开头的文本进行分组”但是如果你没有 3 个字母怎么办?或者差异在后面的某个地方?)
这就是为什么我借助lag
窗口函数(https://www.postgresql.org/docs/current/static/tutorial-window.html)计算特殊组的原因:
SELECT
max(id) as id, -- C
max(phrase) as phrase,
sum("count") as count
FROM (
SELECT
*,
SUM(is_diff) OVER (ORDER BY id, phrase) as ranked -- B
FROM (
SELECT
*,
-- A:
CASE WHEN phrase LIKE (lag(phrase) over (order by id, phrase)) || '%' THEN 0 ELSE 1 END as is_diff
FROM phrases
)s
) s
GROUP BY ranked
ORDER BY ranked
主要思想在这里讨论。
A:该lag
功能允许检查下一行的值。因此,如果phrase
当前行的开头是phrase
下一行的开头,则它们在同一组中。( current_row LIKE (next_row || '%')
)。这是有效的,因为这些id
组是按phrase
文本(及其长度)排序的。
如果行不兼容,则将辅助变量设置为1
,否则设置为0
。
B:可以添加辅助变量并生成组。(有关更多详细信息,请参阅上面提供的链接)。
C:剩下的就是根据新生成的组值进行简单分组。
推荐阅读
- sql - 在 1 到多个表中插入记录
- vuepress - 构建后如何在Vuepress中将外部图像导入为本地资产?
- python - 当我使用 sklearn 进行线性回归时,为什么我只得到一个 coef_?
- spring-boot - 使用 jasypt 时,如何将加密值放入我的配置中?
- php - PHP,从没有循环的对象中返回所有可能的数据
- csv - 如何在 Kibana 中基于同一记录的多个副本创建报表
- reactjs - 无法创建动态下拉列表,因为 useState 首先返回 null,然后返回数据
- sql - 通过在 Oracle SQL 中的数据之间添加文本来更新 SQL 列数据
- python - 如何组织这个 python 结构?
- java - CrudRepostiroy findBy 查询/方法根据原始类型值获取记录,这是一个 ArrayList