sql - 将一列不规则列拆分为多列
问题描述
我需要使用各种分隔符 SQL Server 将一个不规则列拆分为多个子列。
我有一个名为 Event_Name 的列,其中包含以下不规则数据:
EVENT_NAME
----------------
ABBRV
Noun Noun2 Noun3 - Adjective - MM/DD/YYYY - LOCATION
Noun Noun2 - MM/DD/YYYY (#1) - LOCATION
Noun Noun2 - MM/DD/YYYY - Adjective (#1) - LOCATION
Noun, Noun1a Noun2 Noun3 - Adjective: MM/DD/YYYY - Adjective2 - LOCATION
like:
"QRCC"
"Pool Party Dance - Late Night - 12/12/2020 - North"
"Lawn Bowling - 12/12/2020 (#1) - South "
"Lawn, Pool Class Signups - Early: 12/12/2020 - Canceled - North"
"Pool Event - 11/31/2020 - To Be Announced (#1) - South"
我以前尝试使用 Python 解决这个问题,但是现在,管道的结构化方式,我真的需要在 SQL 查询中进行拆分并使用嵌入的日期作为条件。
在 Python 中,我正在研究类似的东西
new= df['Event_Name'].str.split(" ",n=2, expand = True)
new[3] = new[2].str.split("-", expand= True)[1]
new[4] = new[2].str.split("-", expand= True)[2]
new[5] = new[2].str.split("-", expand= True)[3]
new[3] = new[3].str.split(' ()', expand=True)[2]
new[5]=new[2].str[-4:]
data = new[[0,1,3,5]]
0 | 1 | 3 | 5
-------------------------------
Noun | Noun2 | xx/xx/xxxx | LOCATION
但这并没有考虑到形容词,也没有在极少数情况下捕捉到"Noun, Noun1a Noun2 Noun3 - Adjective: MM/DD/YYYY - Adjective - LOCATION"
格式,输出应该是
0 | 1 | 3 | 5
----------------------------------------------
Noun, Noun1a | Noun2| xx/xx/xxxx| LOCATION
所以实际所需的输出将是
(Noun and Noun1a if not null) or ABBRV | Noun2 or null | Noun3 or null | DATE | Adjective or null| Adjective 2 or null| LOCATION
OR
Event Cat | Detail | Detail | DATE | Status | Status | LOCATION
-------------------------------------------------------------
QRCC
Pool | Party | Dance | 12/12/2020 | Late Night | | North
Lawn | Bowling | | 12/12/2020 | | | South
Lawn, Pool| Class | Signups| 12/12/2020 | Early |Canceled |North
Pool |Event | |11/31/2020 | To Be Announced | | South
偶尔"(#1)"
是无关紧要的,可以省略。作为 SQL 调用的一部分,我怎样才能做到这一点?
解决方案
老实说:这个设计很糟糕。任何改变输入的机会都比处理这个要好。这意味着:仅当您无法更改获取数据的方式时,才使用我的建议来解析它。但有时我们不得不处理垃圾......
DECLARE @tbl TABLE(ID INT IDENTITY, YourString VARCHAR(1000));
INSERT INTO @tbl VALUES
('QRCC')
,('Pool Party Dance - Late Night - 12/12/2020 - North')
,('Lawn Bowling - 12/12/2020 (#1) - South')
,('Lawn, Pool Class Signups - Early: 12/12/2020 - Canceled - North')
,('Pool Event - 11/31/2020 - To Be Announced (#1) - South');
--查询
SELECT TheFirstFragment.value('/x[1]','nvarchar(max)') AS [Event Cat]
,TheFirstFragment.value('/x[2]','nvarchar(max)') AS [Detail]
,TheFirstFragment.value('/x[3]','nvarchar(max)') AS [Detail]
,AssumablySomeDate.value('/x[contains(.,"/")][1]','nvarchar(max)') AS HopefullyTheDate
,AssumablySomeDate.value('/x[not(contains(.,"/"))][1]','nvarchar(max)') AS [Status1]
,CASE WHEN TheThirdFragment NOT IN('North','South') AND TheThirdFragment NOT LIKE '%/%' THEN TheThirdFragment END AS [Status2]
,CASE WHEN YourStringAsXml.value('count(/x)','int')>2 THEN YourStringAsXml.value('/x[last()]','nvarchar(max)') END AS [LOCATION]
FROM @tbl t
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT t.YourString AS [*] FOR XML PATH('')),' - ','</x><x>') + '</x>' AS XML)) A(YourStringAsXml)
OUTER APPLY(SELECT Cast('<x>' + REPLACE((SELECT REPLACE(YourStringAsXml.value('/x[1]','nvarchar(max)'),', ',',') AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)) B(TheFirstFragment)
OUTER APPLY(SELECT CAST('<x>' + REPLACE((SELECT YourStringAsXml.value('/x[contains(.,"/")][1]','nvarchar(max)') AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)) C(AssumablySomeDate)
OUTER APPLY(SELECT YourStringAsXml.value('/x[3]','nvarchar(max)')) AS D(TheThirdFragment);
简而言之,这个想法
s将APPLY
预先计算一些列
- 我们使用 XML 在空白破折号空白处将其拆分为片段
- 我们将第一个片段作为在单个空格处重复拆分(但我们必须先处理逗号空格)
- 我们在片段中寻找那个。其中包含一个斜线并将其拆分为单个空白。
- 我们按原样选择第三个片段
栏目列表
- 选取第一个片段的第 1、第 2 和第 3 部分
- 包含斜线的部分可能是日期(但请仔细查看 2020 年 11 月 31 日!)
- 不包含斜线的部分可能是“Early”之类的附加信息
- 第三个片段可能是状态,如果它既不是北,也不是南,也不包含斜线。
- 并且 - 如果有超过 2 个片段,最后一个应该是位置。
使用可能并且应该清楚地表明,这可能随时中断......
推荐阅读
- azure-aks - 如何使用 DNS 在 azure aks 上公开 nginx-ingress
- javascript - 多行显示字符串
- rhel - 使用无根 podman 暴露端口
- python - 如何使用 python 连接到 AMAZON SP_API 端点?
- java - 如何从对流中创建集合映射?
- vb.net - 如何更改 OpenXML word 文档 (vb.net) 中的字体大小?
- flutter - 是否可以使用具有可扩展小部件的 flutter_markdown 自定义构建器?
- facebook - 如何不发送任何查询参数 facebook 像素
- wso2 - Wso2:无法更改 user-mgt.xml
- angular - 授权码授予(WSO2 API Manager 3.2.0)