如何在 SQL 中进行转换和分组
Posted
技术标签:
【中文标题】如何在 SQL 中进行转换和分组【英文标题】:How to transform and grouping in SQL 【发布时间】:2020-05-12 05:53:30 【问题描述】:我想通过将segment
转换为contract date
来对contract date
进行分组,如下所示。
contractdate segment
~2020/2/1 a
2020/2/2~2020/4/1 b
2020/4/2~ c
我想要的结果是将contractdate
分成segment
和count
them 到结果表中。
如果有人有意见,请告诉我。
谢谢
我的桌子如下所示。
contractdate status
2020/1/2 A
2020/4/2 B
2020/6/5 C
2020/1/2 C
2020/4/4 B
这是我想要的结果。
segment A B C
a 1 0 1
b 0 0 0
c 0 2 1
【问题讨论】:
segment
列的源数据从何而来?
请标记RDBS
您正在使用的系统?
它将参考下表~2020/2/1:a 2020/2/2~2020/4/1:b 2020/4/2~:c
我更新了问题,谢谢
我使用oracle
。谢谢
多少个状态码,状态码是多少?你把状态码当作列吗?
【参考方案1】:
用哨兵替换缺失的边界(或者用奇怪的波浪字符替换符号),然后将状态的合同日期分配到适当的范围内:
with sg (contractdate,segment) as (
select '~2020/2/1' , 'a' from dual union all
select '2020/2/2~2020/4/1', 'b' from dual union all
select '2020/4/2~' , 'c' from dual
), ssg as ( -- sanitized sg
select coalesce(to_date(regexp_replace(contractdate,'([^~]*)~([^~]*)','\1'),'YYYY/MM/DD'), date '-4712-1-1') as lowerbound -- source: https://laurentschneider.com/wordpress/2008/01/what-is-the-lowest-and-highest-possible-date-in-oracle.html
, coalesce(to_date(regexp_replace(contractdate,'([^~]*)~([^~]*)','\2'),'YYYY/MM/DD'), date '9999-01-01') as upperbound
, segment
from sg
), st (contractdate,status) as (
select '2020/1/2', 'A' from dual union all
select '2020/4/2', 'B' from dual union all
select '2020/6/5', 'C' from dual union all
select '2020/1/2', 'C' from dual union all
select '2020/4/4', 'B' from dual
)
select segment
, sum(case when status = 'A' then 1 else 0 end)
, sum(case when status = 'B' then 1 else 0 end)
, sum(case when status = 'C' then 1 else 0 end)
from ssg left join st on to_date(st.contractdate,'YYYY/MM/DD') between ssg.lowerbound and ssg.upperbound
group by segment
order by segment
请使用 CTE 指定您的输入数据,而不是明文表格。它有助于专注于答案而不是文本格式。
【讨论】:
以上是关于如何在 SQL 中进行转换和分组的主要内容,如果未能解决你的问题,请参考以下文章