sql - 将奇数行和偶数行显示为 2 个单独的列
问题描述
但给定的要求是:
a~b~c~d~e~f
和 O/p 像:
a b
c d
e f
这里a,e是奇数值,c是偶数值。所以我尝试使用这个查询string_split()
来分隔这个符号'~'。有人可以帮忙吗?
在这个查询中,我没有得到奇怪的偶数列输出:
select
C.CID, c.nunique,
Row Number() OVER (ORDER BY C.CID) as RowNum,
CASE
WHEN (ROW Number () OVER(ORDER BY c.CID)) % 2 = 0 THEN s.value
WHEN (Row Number() OVER (ORDER BY c.CID)) % 2 = 1 THEN s.value
ELSE " invalid"
END
from Candidate c
cross apply STRING SPLIT(applist,~) s
解决方案
回答:
您需要使用拆分器拆分存储的序列以获取子字符串和子字符串的顺序。基于 JSON 的方法在这里可能会有所帮助 - 只需将文本转换为有效的 JSON 数组 ( a~b~c~d~e~f
into ["a","b","c","d","e","f"]'
) 并使用OPENJSON()
. 调用的结果OPENJSON()
是一个带有 columns 的表,key
如果是 JSON 数组,该列包含数组中每个项目的从 0 开始的索引:value
type
key
SELECT c.cid, j.odd, j.even
FROM (VALUES (1, 'a~b~c~d~e~f')) c (cid, applist)
CROSS APPLY (
SELECT
MIN(CASE WHEN CONVERT(int, [key]) % 2 = 0 THEN [value] END) AS [odd],
MIN(CASE WHEN CONVERT(int, [key]) % 2 = 1 THEN [value] END) AS [even]
FROM OPENJSON(CONCAT('["', REPLACE(c.applist, '~', '","'), '"]'))
GROUP BY CONVERT(int, [key]) / 2
) j
结果:
cid odd even
1 a b
1 c d
1 e f
更新:
如果不能选择基于 JSON 的方法,则递归 CTE 可能会有所帮助:
CREATE TABLE Candidate (cid int, applist varchar(max))
INSERT INTO Candidate (cid, applist)
VALUES (1, 'a~b~c~d~e~f'), (2, 'g~h~i~i')
;WITH rCTE AS (
SELECT
c.cid,
LEFT(CONCAT(c.applist, '~'), CHARINDEX('~', CONCAT(c.applist, '~')) - 1) AS substring,
STUFF(CONCAT(c.applist, '~'), 1, CHARINDEX('~', CONCAT(c.applist, '~')), '') AS remaining,
0 AS position
FROM Candidate c
UNION ALL
SELECT
r.cid,
LEFT(r.remaining, CHARINDEX('~', r.remaining) - 1),
STUFF(r.remaining, 1, CHARINDEX('~', r.remaining), ''),
r.position + 1
FROM rCTE r
WHERE LEN(r.remaining) > 0
)
SELECT
cid,
MIN(CASE WHEN position % 2 = 0 THEN [substring] END) AS [odd],
MIN(CASE WHEN position % 2 = 1 THEN [substring] END) AS [even]
FROM rCTE
GROUP BY cid, position / 2
OPTION (MAXRECURSION 0);
使用STRING_SPLIT()
:
请注意,虽然STRING_SPLIT()
是一个选项,但请谨慎使用此函数,因为如文档中所述,输出行可能是任何顺序,并且不能保证该顺序与输入字符串中子字符串的顺序相匹配。
SELECT
c.cid,
MIN(CASE WHEN rn % 2 = 0 THEN [value] END) AS [odd],
MIN(CASE WHEN rn % 2 = 1 THEN [value] END) AS [even]
FROM (VALUES
(1, 'a~b~c~d~e~f'),
(2, 'g~h~i~i')
) c (cid, applist)
CROSS APPLY (
SELECT [value], ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 rn
FROM STRING_SPLIT(c.applist, '~')
) s
GROUP BY c.cid, s.rn / 2
推荐阅读
- typescript - TypeScript:如何在不指定模板参数的情况下使用模板类型?
- azure-blob-storage - 将 json 文档归档到 Azure Blob 存储的最佳做法是什么?
- android - 在按钮上显示 google play 购买菜单 点击
- neural-network - PyTorch 迭代修剪
- docker - Traefik CouchDB 问题
- vue.js - Vue Jest 测试循环等待
- git - 从控制台/詹金斯隐藏 GitSCM 输出
- java - ConsoleLoggerManager.getLoggerForComponent 在启动 Fitnesse 时给出 NullPointerException
- android - 将 FirebaseAuth 模拟器连接到 Kotlin Android 项目
- prolog - 多集序言中的包含函数